Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Dec 2000 12:46:41 -0800 (PST)
From:      Luigi Rizzo <rizzo@aciri.org>
To:        andy@andy.de (Andreas Gerstenberg)
Cc:        freebsd-net@FreeBSD.ORG, itojun@FreeBSD.ORG
Subject:   Re: GRE implementation?
Message-ID:  <200012212046.eBLKkfe87614@iguana.aciri.org>
In-Reply-To: <2476561115.977434137@windoze.andy.de> from Andreas Gerstenberg at "Dec 21, 2000  9:28:57 pm"

next in thread | previous in thread | raw e-mail | index | archive | help
> 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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200012212046.eBLKkfe87614>