Re: eoip(4): MikroTik Ethernet over IP support

2018-05-28 Thread Michael W. Bombardieri
On Sun, May 27, 2018 at 10:18:30AM +1000, David Gwynne wrote:
> this implements MikroTiks Ethernet over IP protocol support.
> 
> The Mikrotik protocol is basically GRE, so this is implemented as
> eoip(4) as (yet another) part of if_gre. the main differences between
> egre and eoip is that eoip uses gre version 1 (not 0) and 0x6400
> as the protocol identifier (not transparent ethernet as per rfc
> 1701), mandates a key header, but splits the key into 16bit len and
> tunnel id fields (a bit like pptp).
> 
> the keepalive semantics are also different. keepalives are just 0
> length packets, and arent echoed. each side listens for the others
> packet to see if theyre up, but doesn't relay the keepalives. theyre
> more hellos maybe?
> 
> like egre though, it still misaligns the payload, but what doesnt
> these days?
> 
> this also tweaks tcpdump to better support the protocol.

Hello,

In gre_ioctl(), mgre_ioctl(), egre_ioctl() and eoip_ioctl() the
SIOCSIFFLAGS case appears to have code that explicitly sets error=0
but it looks like error is already zero unless I'm reading it wrong.
Also, nvgre_ioctl() is different because it seems to set error=ENETRESET
in that case (i.e. IFF_UP and IFF_RUNNING are both set). Is that
difference intended?

- Michael



eoip(4): MikroTik Ethernet over IP support

2018-05-26 Thread David Gwynne
this implements MikroTiks Ethernet over IP protocol support.

The Mikrotik protocol is basically GRE, so this is implemented as
eoip(4) as (yet another) part of if_gre. the main differences between
egre and eoip is that eoip uses gre version 1 (not 0) and 0x6400
as the protocol identifier (not transparent ethernet as per rfc
1701), mandates a key header, but splits the key into 16bit len and
tunnel id fields (a bit like pptp).

the keepalive semantics are also different. keepalives are just 0
length packets, and arent echoed. each side listens for the others
packet to see if theyre up, but doesn't relay the keepalives. theyre
more hellos maybe?

like egre though, it still misaligns the payload, but what doesnt
these days?

this also tweaks tcpdump to better support the protocol.

ok?

Index: sys/net/if_gre.c
===
RCS file: /cvs/src/sys/net/if_gre.c,v
retrieving revision 1.122
diff -u -p -r1.122 if_gre.c
--- sys/net/if_gre.c12 Mar 2018 12:47:35 -  1.122
+++ sys/net/if_gre.c27 May 2018 00:12:36 -
@@ -124,6 +124,13 @@ struct gre_h_key {
uint32_tgre_key;
 } __packed __aligned(4);
 
+#define GRE_EOIP   0x6400
+
+struct gre_h_key_eoip {
+   uint16_teoip_len;   /* network order */
+   uint16_teoip_tunnel_id; /* little endian */
+} __packed __aligned(4);
+
 #define NVGRE_VSID_RES_MIN 0x00 /* reserved for future use */
 #define NVGRE_VSID_RES_MAX 0x000fff
 #define NVGRE_VSID_NVE2NVE 0xff /* vendor specific NVE-to-NVE comms */
@@ -211,6 +218,12 @@ static struct mbuf *
 #define gre_encap(_t, _m, _p, _ttl, _tos) \
gre_encap_dst((_t), &(_t)->t_dst, (_m), (_p), (_ttl), (_tos))
 
+static struct mbuf *
+   gre_encap_dst_ip(const struct gre_tunnel *,
+   const union gre_addr *, struct mbuf *, uint8_t, uint8_t);
+#define gre_encap_ip(_t, _m, _ttl, _tos) \
+   gre_encap_dst_ip((_t), &(_t)->t_dst, (_m), (_ttl), (_tos))
+
 static int
gre_ip_output(const struct gre_tunnel *, struct mbuf *);
 
@@ -266,7 +279,7 @@ static int  gre_ioctl(struct ifnet *, u_l
 
 static int gre_up(struct gre_softc *);
 static int gre_down(struct gre_softc *);
-static voidgre_link_state(struct gre_softc *);
+static voidgre_link_state(struct ifnet *, unsigned int);
 
 static int gre_input_key(struct mbuf **, int *, int, int,
struct gre_tunnel *);
@@ -457,6 +470,61 @@ struct nvgre_ucast_tree nvgre_ucast_tree
 struct nvgre_mcast_tree nvgre_mcast_tree = RBT_INITIALIZER();
 
 /*
+ * MikroTik Ethernet over IP protocol (eoip)
+ */
+
+struct eoip_softc {
+   struct gre_tunnel   sc_tunnel; /* must be first */
+   uint16_tsc_tunnel_id;
+   RBT_ENTRY(eoip_softc)   sc_entry;
+
+   struct arpcom   sc_ac;
+   struct ifmedia  sc_media;
+
+   struct timeout  sc_ka_send;
+   struct timeout  sc_ka_hold;
+
+   unsigned intsc_ka_state;
+   unsigned intsc_ka_timeo;
+   unsigned intsc_ka_count;
+
+   unsigned intsc_ka_holdmax;
+   unsigned intsc_ka_holdcnt;
+};
+
+RBT_HEAD(eoip_tree, eoip_softc);
+
+static inline int
+   eoip_cmp(const struct eoip_softc *, const struct eoip_softc *);
+
+RBT_PROTOTYPE(eoip_tree, eoip_softc, sc_entry, eoip_cmp);
+
+static int eoip_clone_create(struct if_clone *, int);
+static int eoip_clone_destroy(struct ifnet *);
+
+static voideoip_start(struct ifnet *);
+static int eoip_ioctl(struct ifnet *, u_long, caddr_t);
+
+static voideoip_keepalive_send(void *);
+static voideoip_keepalive_recv(struct eoip_softc *);
+static voideoip_keepalive_hold(void *);
+
+static int eoip_up(struct eoip_softc *);
+static int eoip_down(struct eoip_softc *);
+
+static struct mbuf *
+   eoip_encap(struct eoip_softc *, struct mbuf *, uint8_t);
+
+static struct mbuf *
+   eoip_input(struct gre_tunnel *, struct mbuf *,
+   const struct gre_header *, int);
+struct if_clone eoip_cloner =
+IF_CLONE_INITIALIZER("eoip", eoip_clone_create, eoip_clone_destroy);
+ 
+/* protected by NET_LOCK */
+struct eoip_tree eoip_tree = RBT_INITIALIZER();
+
+/*
  * It is not easy to calculate the right value for a GRE MTU.
  * We leave this task to the admin and use the same default that
  * other vendors use.
@@ -482,6 +550,7 @@ greattach(int n)
if_clone_attach(_cloner);
if_clone_attach(_cloner);
if_clone_attach(_cloner);
+   if_clone_attach(_cloner);
 }
 
 static int
@@ -725,6 +794,65 @@ nvgre_clone_destroy(struct ifnet *ifp)
return (0);
 }
 
+static int
+eoip_clone_create(struct if_clone *ifc, int unit)
+{
+   struct eoip_softc *sc;
+   struct ifnet *ifp;
+
+   sc = malloc(sizeof(*sc), M_DEVBUF,