From owner-freebsd-net Thu Dec 21 12:47: 1 2000 From owner-freebsd-net@FreeBSD.ORG Thu Dec 21 12:46:56 2000 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from iguana.aciri.org (iguana.aciri.org [192.150.187.36]) by hub.freebsd.org (Postfix) with ESMTP id 0E12837B400; Thu, 21 Dec 2000 12:46:56 -0800 (PST) Received: (from rizzo@localhost) by iguana.aciri.org (8.11.1/8.11.1) id eBLKkfe87614; Thu, 21 Dec 2000 12:46:41 -0800 (PST) (envelope-from rizzo) From: Luigi Rizzo Message-Id: <200012212046.eBLKkfe87614@iguana.aciri.org> Subject: Re: GRE implementation? In-Reply-To: <2476561115.977434137@windoze.andy.de> from Andreas Gerstenberg at "Dec 21, 2000 9:28:57 pm" To: andy@andy.de (Andreas Gerstenberg) Date: Thu, 21 Dec 2000 12:46:41 -0800 (PST) Cc: freebsd-net@FreeBSD.ORG, itojun@FreeBSD.ORG X-Mailer: ELM [version 2.4ME+ PL43 (25)] MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: rizzo@iguana.aciri.org Sender: owner-freebsd-net@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org > Hi, > > I just want to ask if there are plans to implement GRE encapsulation e.g. for > setup tunnel interfaces with cisco routers? some time ago i hacked the "gif" interface to support GRE -- you need to set the 'link2' flag to enable GRE on that interface. It does not support checksums, but apparently our cisco does not seem to use them (by default at least). Patches for 4.1 are attached. They are rather simple and short, and i think they pretty much do the job (GRE is quite simple, anyways). Note though that itojun warned me that this code might conflict with future use of the link2 flag from the KAME project. He also suggested to implement GRE as a different "interface", though I am not sure it is worth the effort given the excellent infrastructure provided by the KAME people for the gif/faith etc. interfaces (which is the main reason why the attached diffs are so small). Actually if people have comments i would like to hear. cheers luigi Index: sys/net/if_gif.c =================================================================== RCS file: /home/iguana/u0/rizzo/ncvs/src/sys/net/if_gif.c,v retrieving revision 1.4.2.2 diff -u -r1.4.2.2 if_gif.c --- sys/net/if_gif.c 2000/07/20 00:45:07 1.4.2.2 +++ sys/net/if_gif.c 2000/10/31 01:26:57 @@ -121,14 +121,23 @@ gif = sc = malloc (ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAIT); bzero(sc, ngif * sizeof(struct gif_softc)); for (i = 0; i < ngif; sc++, i++) { + void *gre_cookie = NULL ; + sc->gif_if.if_name = "gif"; sc->gif_if.if_unit = i; sc->encap_cookie4 = sc->encap_cookie6 = NULL; #ifdef INET + gre_cookie = encap_attach_func(AF_INET, IPPROTO_GRE, + gif_encapcheck, &in_gif_protosw, sc); + if (gre_cookie == NULL) + continue ; + sc->encap_cookie4 = encap_attach_func(AF_INET, -1, gif_encapcheck, &in_gif_protosw, sc); if (sc->encap_cookie4 == NULL) { + if (gre_cookie) + encap_detach(gre_cookie); printf("%s: attach failed\n", if_name(&sc->gif_if)); continue; } @@ -141,6 +150,8 @@ encap_detach(sc->encap_cookie4); sc->encap_cookie4 = NULL; } + if (gre_cookie) + encap_detach(gre_cookie); printf("%s: attach failed\n", if_name(&sc->gif_if)); continue; } @@ -189,6 +200,7 @@ switch (proto) { #ifdef INET case IPPROTO_IPV4: + case IPPROTO_GRE: break; #endif #ifdef INET6 Index: sys/netinet/in_gif.c =================================================================== RCS file: /home/iguana/u0/rizzo/ncvs/src/sys/netinet/in_gif.c,v retrieving revision 1.5.2.1 diff -u -r1.5.2.1 in_gif.c --- sys/netinet/in_gif.c 2000/07/15 07:14:30 1.5.2.1 +++ sys/netinet/in_gif.c 2000/10/31 04:02:06 @@ -99,6 +99,7 @@ struct ip iphdr; /* capsule IP header, host byte ordered */ int proto, error; u_int8_t tos; + int phl = sizeof(struct ip); /* prepend header length */ if (sin_src == NULL || sin_dst == NULL || sin_src->sin_family != AF_INET || @@ -114,6 +115,11 @@ struct ip *ip; proto = IPPROTO_IPV4; + if (ifp->if_flags & IFF_LINK2) {/* a GRE tunnel */ + printf("gif_output: GRE!\n"); + proto = IPPROTO_GRE; + phl = sizeof(struct ip) + 4 ; /* GRE header, no checksum */ + } if (m->m_len < sizeof(*ip)) { m = m_pullup(m, sizeof(*ip)); if (!m) @@ -177,19 +183,25 @@ iphdr.ip_p = proto; /* version will be set in ip_output() */ iphdr.ip_ttl = ip_gif_ttl; - iphdr.ip_len = m->m_pkthdr.len + sizeof(struct ip); + iphdr.ip_len = m->m_pkthdr.len + phl ; if (ifp->if_flags & IFF_LINK1) ip_ecn_ingress(ECN_ALLOWED, &iphdr.ip_tos, &tos); /* prepend new IP header */ - M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); - if (m && m->m_len < sizeof(struct ip)) - m = m_pullup(m, sizeof(struct ip)); + M_PREPEND(m, phl, M_DONTWAIT); + if (m && m->m_len < phl) + m = m_pullup(m, phl); if (m == NULL) { printf("ENOBUFS in in_gif_output %d\n", __LINE__); return ENOBUFS; } bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip)); + if (proto == IPPROTO_GRE) { /* fill GRE header */ + u_int16_t *p ; + (void *)p = mtod(m, void *) + sizeof(struct ip); + p[0] = 0 ; + p[1] = htons(0x800 /* ETHERTYPE_IP */); + } if (dst->sin_family != sin_dst->sin_family || dst->sin_addr.s_addr != sin_dst->sin_addr.s_addr) { @@ -260,6 +272,14 @@ } otos = ip->ip_tos; + if (proto == IPPROTO_GRE) { + u_char *p = (u_char *)(ip) + off ; + printf("in_gif_input: GRE\n"); + off += 4 ; /* strip off GRE header */ + if (p[0] & 1) + off += 4 ; /* strip off checksum */ + proto = IPPROTO_IPV4 ; /* XXX hack! */ + } m_adj(m, off); switch (proto) { Index: sys/netinet/in_proto.c =================================================================== RCS file: /home/iguana/u0/rizzo/ncvs/src/sys/netinet/in_proto.c,v retrieving revision 1.53.2.1 diff -u -r1.53.2.1 in_proto.c --- sys/netinet/in_proto.c 2000/07/15 07:14:30 1.53.2.1 +++ sys/netinet/in_proto.c 2000/10/31 01:05:18 @@ -165,6 +165,12 @@ encap_init, 0, 0, 0, &nousrreqs }, +{ SOCK_RAW, &inetdomain, IPPROTO_GRE, PR_ATOMIC|PR_ADDR, + encap4_input, 0, 0, rip_ctloutput, + 0, + encap_init, 0, 0, 0, + &nousrreqs +}, # ifdef INET6 { SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR, encap4_input, 0, 0, rip_ctloutput, To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-net" in the body of the message