aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2008-10-09 15:00:17 -0400
committerDavid S. Miller <davem@davemloft.net>2008-10-09 15:00:17 -0400
commite1a8000228e16212c93b23cfbed4d622e2ec7a6b (patch)
tree8a2b26a105abea23778228e7ea6d95500037a632 /net
parentc19e654ddbe3831252f61e76a74d661e1a755530 (diff)
gre: Add Transparent Ethernet Bridging
This patch adds support for Ethernet over GRE encapsulation. This is exposed to user-space with a new link type of "gretap" instead of "gre". It will create an ARPHRD_ETHER device in lieu of the usual ARPHRD_IPGRE. Note that to preserver backwards compatibility all Transparent Ethernet Bridging packets are passed to an ARPHRD_IPGRE tunnel if its key matches and there is no ARPHRD_ETHER device whose key matches more closely. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/ip_gre.c206
1 files changed, 174 insertions, 32 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 25d2c77a7f38..44ed9487fa15 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -27,6 +27,7 @@
27#include <linux/inetdevice.h> 27#include <linux/inetdevice.h>
28#include <linux/igmp.h> 28#include <linux/igmp.h>
29#include <linux/netfilter_ipv4.h> 29#include <linux/netfilter_ipv4.h>
30#include <linux/etherdevice.h>
30#include <linux/if_ether.h> 31#include <linux/if_ether.h>
31 32
32#include <net/sock.h> 33#include <net/sock.h>
@@ -166,38 +167,64 @@ static DEFINE_RWLOCK(ipgre_lock);
166/* Given src, dst and key, find appropriate for input tunnel. */ 167/* Given src, dst and key, find appropriate for input tunnel. */
167 168
168static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net, 169static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net,
169 __be32 remote, __be32 local, __be32 key) 170 __be32 remote, __be32 local,
171 __be32 key, __be16 gre_proto)
170{ 172{
171 unsigned h0 = HASH(remote); 173 unsigned h0 = HASH(remote);
172 unsigned h1 = HASH(key); 174 unsigned h1 = HASH(key);
173 struct ip_tunnel *t; 175 struct ip_tunnel *t;
176 struct ip_tunnel *t2 = NULL;
174 struct ipgre_net *ign = net_generic(net, ipgre_net_id); 177 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
178 int dev_type = (gre_proto == htons(ETH_P_TEB)) ?
179 ARPHRD_ETHER : ARPHRD_IPGRE;
175 180
176 for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) { 181 for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) {
177 if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { 182 if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {
178 if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) 183 if (t->parms.i_key == key && t->dev->flags & IFF_UP) {
179 return t; 184 if (t->dev->type == dev_type)
185 return t;
186 if (t->dev->type == ARPHRD_IPGRE && !t2)
187 t2 = t;
188 }
180 } 189 }
181 } 190 }
191
182 for (t = ign->tunnels_r[h0^h1]; t; t = t->next) { 192 for (t = ign->tunnels_r[h0^h1]; t; t = t->next) {
183 if (remote == t->parms.iph.daddr) { 193 if (remote == t->parms.iph.daddr) {
184 if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) 194 if (t->parms.i_key == key && t->dev->flags & IFF_UP) {
185 return t; 195 if (t->dev->type == dev_type)
196 return t;
197 if (t->dev->type == ARPHRD_IPGRE && !t2)
198 t2 = t;
199 }
186 } 200 }
187 } 201 }
202
188 for (t = ign->tunnels_l[h1]; t; t = t->next) { 203 for (t = ign->tunnels_l[h1]; t; t = t->next) {
189 if (local == t->parms.iph.saddr || 204 if (local == t->parms.iph.saddr ||
190 (local == t->parms.iph.daddr && 205 (local == t->parms.iph.daddr &&
191 ipv4_is_multicast(local))) { 206 ipv4_is_multicast(local))) {
192 if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) 207 if (t->parms.i_key == key && t->dev->flags & IFF_UP) {
193 return t; 208 if (t->dev->type == dev_type)
209 return t;
210 if (t->dev->type == ARPHRD_IPGRE && !t2)
211 t2 = t;
212 }
194 } 213 }
195 } 214 }
215
196 for (t = ign->tunnels_wc[h1]; t; t = t->next) { 216 for (t = ign->tunnels_wc[h1]; t; t = t->next) {
197 if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) 217 if (t->parms.i_key == key && t->dev->flags & IFF_UP) {
198 return t; 218 if (t->dev->type == dev_type)
219 return t;
220 if (t->dev->type == ARPHRD_IPGRE && !t2)
221 t2 = t;
222 }
199 } 223 }
200 224
225 if (t2)
226 return t2;
227
201 if (ign->fb_tunnel_dev->flags&IFF_UP) 228 if (ign->fb_tunnel_dev->flags&IFF_UP)
202 return netdev_priv(ign->fb_tunnel_dev); 229 return netdev_priv(ign->fb_tunnel_dev);
203 return NULL; 230 return NULL;
@@ -252,25 +279,37 @@ static void ipgre_tunnel_unlink(struct ipgre_net *ign, struct ip_tunnel *t)
252 } 279 }
253} 280}
254 281
255static struct ip_tunnel * ipgre_tunnel_locate(struct net *net, 282static struct ip_tunnel *ipgre_tunnel_find(struct net *net,
256 struct ip_tunnel_parm *parms, int create) 283 struct ip_tunnel_parm *parms,
284 int type)
257{ 285{
258 __be32 remote = parms->iph.daddr; 286 __be32 remote = parms->iph.daddr;
259 __be32 local = parms->iph.saddr; 287 __be32 local = parms->iph.saddr;
260 __be32 key = parms->i_key; 288 __be32 key = parms->i_key;
261 struct ip_tunnel *t, **tp, *nt; 289 struct ip_tunnel *t, **tp;
290 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
291
292 for (tp = __ipgre_bucket(ign, parms); (t = *tp) != NULL; tp = &t->next)
293 if (local == t->parms.iph.saddr &&
294 remote == t->parms.iph.daddr &&
295 key == t->parms.i_key &&
296 type == t->dev->type)
297 break;
298
299 return t;
300}
301
302static struct ip_tunnel * ipgre_tunnel_locate(struct net *net,
303 struct ip_tunnel_parm *parms, int create)
304{
305 struct ip_tunnel *t, *nt;
262 struct net_device *dev; 306 struct net_device *dev;
263 char name[IFNAMSIZ]; 307 char name[IFNAMSIZ];
264 struct ipgre_net *ign = net_generic(net, ipgre_net_id); 308 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
265 309
266 for (tp = __ipgre_bucket(ign, parms); (t = *tp) != NULL; tp = &t->next) { 310 t = ipgre_tunnel_find(net, parms, ARPHRD_IPGRE);
267 if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { 311 if (t || !create)
268 if (key == t->parms.i_key) 312 return t;
269 return t;
270 }
271 }
272 if (!create)
273 return NULL;
274 313
275 if (parms->name[0]) 314 if (parms->name[0])
276 strlcpy(name, parms->name, IFNAMSIZ); 315 strlcpy(name, parms->name, IFNAMSIZ);
@@ -385,8 +424,9 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
385 424
386 read_lock(&ipgre_lock); 425 read_lock(&ipgre_lock);
387 t = ipgre_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr, 426 t = ipgre_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr,
388 (flags&GRE_KEY) ? 427 flags & GRE_KEY ?
389 *(((__be32*)p) + (grehlen>>2) - 1) : 0); 428 *(((__be32 *)p) + (grehlen / 4) - 1) : 0,
429 p[1]);
390 if (t == NULL || t->parms.iph.daddr == 0 || 430 if (t == NULL || t->parms.iph.daddr == 0 ||
391 ipv4_is_multicast(t->parms.iph.daddr)) 431 ipv4_is_multicast(t->parms.iph.daddr))
392 goto out; 432 goto out;
@@ -436,6 +476,7 @@ static int ipgre_rcv(struct sk_buff *skb)
436 u32 seqno = 0; 476 u32 seqno = 0;
437 struct ip_tunnel *tunnel; 477 struct ip_tunnel *tunnel;
438 int offset = 4; 478 int offset = 4;
479 __be16 gre_proto;
439 480
440 if (!pskb_may_pull(skb, 16)) 481 if (!pskb_may_pull(skb, 16))
441 goto drop_nolock; 482 goto drop_nolock;
@@ -475,20 +516,22 @@ static int ipgre_rcv(struct sk_buff *skb)
475 } 516 }
476 } 517 }
477 518
519 gre_proto = *(__be16 *)(h + 2);
520
478 read_lock(&ipgre_lock); 521 read_lock(&ipgre_lock);
479 if ((tunnel = ipgre_tunnel_lookup(dev_net(skb->dev), 522 if ((tunnel = ipgre_tunnel_lookup(dev_net(skb->dev),
480 iph->saddr, iph->daddr, key)) != NULL) { 523 iph->saddr, iph->daddr, key,
524 gre_proto))) {
481 struct net_device_stats *stats = &tunnel->dev->stats; 525 struct net_device_stats *stats = &tunnel->dev->stats;
482 526
483 secpath_reset(skb); 527 secpath_reset(skb);
484 528
485 skb->protocol = *(__be16*)(h + 2); 529 skb->protocol = gre_proto;
486 /* WCCP version 1 and 2 protocol decoding. 530 /* WCCP version 1 and 2 protocol decoding.
487 * - Change protocol to IP 531 * - Change protocol to IP
488 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header 532 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
489 */ 533 */
490 if (flags == 0 && 534 if (flags == 0 && gre_proto == htons(ETH_P_WCCP)) {
491 skb->protocol == htons(ETH_P_WCCP)) {
492 skb->protocol = htons(ETH_P_IP); 535 skb->protocol = htons(ETH_P_IP);
493 if ((*(h + offset) & 0xF0) != 0x40) 536 if ((*(h + offset) & 0xF0) != 0x40)
494 offset += 4; 537 offset += 4;
@@ -496,7 +539,6 @@ static int ipgre_rcv(struct sk_buff *skb)
496 539
497 skb->mac_header = skb->network_header; 540 skb->mac_header = skb->network_header;
498 __pskb_pull(skb, offset); 541 __pskb_pull(skb, offset);
499 skb_reset_network_header(skb);
500 skb_postpull_rcsum(skb, skb_transport_header(skb), offset); 542 skb_postpull_rcsum(skb, skb_transport_header(skb), offset);
501 skb->pkt_type = PACKET_HOST; 543 skb->pkt_type = PACKET_HOST;
502#ifdef CONFIG_NET_IPGRE_BROADCAST 544#ifdef CONFIG_NET_IPGRE_BROADCAST
@@ -524,13 +566,30 @@ static int ipgre_rcv(struct sk_buff *skb)
524 } 566 }
525 tunnel->i_seqno = seqno + 1; 567 tunnel->i_seqno = seqno + 1;
526 } 568 }
569
570 /* Warning: All skb pointers will be invalidated! */
571 if (tunnel->dev->type == ARPHRD_ETHER) {
572 if (!pskb_may_pull(skb, ETH_HLEN)) {
573 stats->rx_length_errors++;
574 stats->rx_errors++;
575 goto drop;
576 }
577
578 iph = ip_hdr(skb);
579 skb->protocol = eth_type_trans(skb, tunnel->dev);
580 skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
581 }
582
527 stats->rx_packets++; 583 stats->rx_packets++;
528 stats->rx_bytes += skb->len; 584 stats->rx_bytes += skb->len;
529 skb->dev = tunnel->dev; 585 skb->dev = tunnel->dev;
530 dst_release(skb->dst); 586 dst_release(skb->dst);
531 skb->dst = NULL; 587 skb->dst = NULL;
532 nf_reset(skb); 588 nf_reset(skb);
589
590 skb_reset_network_header(skb);
533 ipgre_ecn_decapsulate(iph, skb); 591 ipgre_ecn_decapsulate(iph, skb);
592
534 netif_rx(skb); 593 netif_rx(skb);
535 read_unlock(&ipgre_lock); 594 read_unlock(&ipgre_lock);
536 return(0); 595 return(0);
@@ -565,7 +624,10 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
565 goto tx_error; 624 goto tx_error;
566 } 625 }
567 626
568 if (dev->header_ops) { 627 if (dev->type == ARPHRD_ETHER)
628 IPCB(skb)->flags = 0;
629
630 if (dev->header_ops && dev->type == ARPHRD_IPGRE) {
569 gre_hlen = 0; 631 gre_hlen = 0;
570 tiph = (struct iphdr*)skb->data; 632 tiph = (struct iphdr*)skb->data;
571 } else { 633 } else {
@@ -741,8 +803,9 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
741 iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT); 803 iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT);
742 } 804 }
743 805
744 ((__be16*)(iph+1))[0] = tunnel->parms.o_flags; 806 ((__be16 *)(iph + 1))[0] = tunnel->parms.o_flags;
745 ((__be16*)(iph+1))[1] = skb->protocol; 807 ((__be16 *)(iph + 1))[1] = (dev->type == ARPHRD_ETHER) ?
808 htons(ETH_P_TEB) : skb->protocol;
746 809
747 if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) { 810 if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) {
748 __be32 *ptr = (__be32*)(((u8*)iph) + tunnel->hlen - 4); 811 __be32 *ptr = (__be32*)(((u8*)iph) + tunnel->hlen - 4);
@@ -804,7 +867,9 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev)
804 tdev = rt->u.dst.dev; 867 tdev = rt->u.dst.dev;
805 ip_rt_put(rt); 868 ip_rt_put(rt);
806 } 869 }
807 dev->flags |= IFF_POINTOPOINT; 870
871 if (dev->type != ARPHRD_ETHER)
872 dev->flags |= IFF_POINTOPOINT;
808 } 873 }
809 874
810 if (!tdev && tunnel->parms.link) 875 if (!tdev && tunnel->parms.link)
@@ -1250,6 +1315,30 @@ static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
1250 return 0; 1315 return 0;
1251} 1316}
1252 1317
1318static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[])
1319{
1320 __be32 daddr;
1321
1322 if (tb[IFLA_ADDRESS]) {
1323 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
1324 return -EINVAL;
1325 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
1326 return -EADDRNOTAVAIL;
1327 }
1328
1329 if (!data)
1330 goto out;
1331
1332 if (data[IFLA_GRE_REMOTE]) {
1333 memcpy(&daddr, nla_data(data[IFLA_GRE_REMOTE]), 4);
1334 if (!daddr)
1335 return -EINVAL;
1336 }
1337
1338out:
1339 return ipgre_tunnel_validate(tb, data);
1340}
1341
1253static void ipgre_netlink_parms(struct nlattr *data[], 1342static void ipgre_netlink_parms(struct nlattr *data[],
1254 struct ip_tunnel_parm *parms) 1343 struct ip_tunnel_parm *parms)
1255{ 1344{
@@ -1291,6 +1380,35 @@ static void ipgre_netlink_parms(struct nlattr *data[],
1291 parms->iph.frag_off = htons(IP_DF); 1380 parms->iph.frag_off = htons(IP_DF);
1292} 1381}
1293 1382
1383static int ipgre_tap_init(struct net_device *dev)
1384{
1385 struct ip_tunnel *tunnel;
1386
1387 tunnel = netdev_priv(dev);
1388
1389 tunnel->dev = dev;
1390 strcpy(tunnel->parms.name, dev->name);
1391
1392 ipgre_tunnel_bind_dev(dev);
1393
1394 return 0;
1395}
1396
1397static void ipgre_tap_setup(struct net_device *dev)
1398{
1399
1400 ether_setup(dev);
1401
1402 dev->init = ipgre_tap_init;
1403 dev->uninit = ipgre_tunnel_uninit;
1404 dev->destructor = free_netdev;
1405 dev->hard_start_xmit = ipgre_tunnel_xmit;
1406 dev->change_mtu = ipgre_tunnel_change_mtu;
1407
1408 dev->iflink = 0;
1409 dev->features |= NETIF_F_NETNS_LOCAL;
1410}
1411
1294static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[], 1412static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[],
1295 struct nlattr *data[]) 1413 struct nlattr *data[])
1296{ 1414{
@@ -1303,9 +1421,12 @@ static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[],
1303 nt = netdev_priv(dev); 1421 nt = netdev_priv(dev);
1304 ipgre_netlink_parms(data, &nt->parms); 1422 ipgre_netlink_parms(data, &nt->parms);
1305 1423
1306 if (ipgre_tunnel_locate(net, &nt->parms, 0)) 1424 if (ipgre_tunnel_find(net, &nt->parms, dev->type))
1307 return -EEXIST; 1425 return -EEXIST;
1308 1426
1427 if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS])
1428 random_ether_addr(dev->dev_addr);
1429
1309 mtu = ipgre_tunnel_bind_dev(dev); 1430 mtu = ipgre_tunnel_bind_dev(dev);
1310 if (!tb[IFLA_MTU]) 1431 if (!tb[IFLA_MTU])
1311 dev->mtu = mtu; 1432 dev->mtu = mtu;
@@ -1455,6 +1576,19 @@ static struct rtnl_link_ops ipgre_link_ops __read_mostly = {
1455 .fill_info = ipgre_fill_info, 1576 .fill_info = ipgre_fill_info,
1456}; 1577};
1457 1578
1579static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
1580 .kind = "gretap",
1581 .maxtype = IFLA_GRE_MAX,
1582 .policy = ipgre_policy,
1583 .priv_size = sizeof(struct ip_tunnel),
1584 .setup = ipgre_tap_setup,
1585 .validate = ipgre_tap_validate,
1586 .newlink = ipgre_newlink,
1587 .changelink = ipgre_changelink,
1588 .get_size = ipgre_get_size,
1589 .fill_info = ipgre_fill_info,
1590};
1591
1458/* 1592/*
1459 * And now the modules code and kernel interface. 1593 * And now the modules code and kernel interface.
1460 */ 1594 */
@@ -1478,9 +1612,15 @@ static int __init ipgre_init(void)
1478 if (err < 0) 1612 if (err < 0)
1479 goto rtnl_link_failed; 1613 goto rtnl_link_failed;
1480 1614
1615 err = rtnl_link_register(&ipgre_tap_ops);
1616 if (err < 0)
1617 goto tap_ops_failed;
1618
1481out: 1619out:
1482 return err; 1620 return err;
1483 1621
1622tap_ops_failed:
1623 rtnl_link_unregister(&ipgre_link_ops);
1484rtnl_link_failed: 1624rtnl_link_failed:
1485 unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops); 1625 unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops);
1486gen_device_failed: 1626gen_device_failed:
@@ -1490,6 +1630,7 @@ gen_device_failed:
1490 1630
1491static void __exit ipgre_fini(void) 1631static void __exit ipgre_fini(void)
1492{ 1632{
1633 rtnl_link_unregister(&ipgre_tap_ops);
1493 rtnl_link_unregister(&ipgre_link_ops); 1634 rtnl_link_unregister(&ipgre_link_ops);
1494 unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops); 1635 unregister_pernet_gen_device(ipgre_net_id, &ipgre_net_ops);
1495 if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) 1636 if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
@@ -1500,3 +1641,4 @@ module_init(ipgre_init);
1500module_exit(ipgre_fini); 1641module_exit(ipgre_fini);
1501MODULE_LICENSE("GPL"); 1642MODULE_LICENSE("GPL");
1502MODULE_ALIAS("rtnl-link-gre"); 1643MODULE_ALIAS("rtnl-link-gre");
1644MODULE_ALIAS("rtnl-link-gretap");