diff options
author | Atzm Watanabe <atzm@stratosphere.co.jp> | 2013-04-15 22:50:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-04-16 16:43:35 -0400 |
commit | c7995c43facc6e5dea4de63fa9d283a337aabeb1 (patch) | |
tree | 3543a212031bc507ecc14b6d4b1f92bb7d957feb /drivers/net/vxlan.c | |
parent | 184f489e9b8c40b4dd4883d3f1364f7786c8755c (diff) |
vxlan: Allow setting destination to unicast address.
This patch allows setting VXLAN destination to unicast address.
It allows that VXLAN can be used as peer-to-peer tunnel without
multicast.
v4: generalize struct vxlan_dev, "gaddr" is replaced with vxlan_rdst.
"GROUP" attribute is replaced with "REMOTE".
they are based by David Stevens's comments.
v3: move a new attribute REMOTE into the last of an enum list
based by Stephen Hemminger's comments.
v2: use a new attribute REMOTE instead of GROUP based by
Cong Wang's comments.
Signed-off-by: Atzm Watanabe <atzm@stratosphere.co.jp>
Acked-by: David L Stevens <dlstevens@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r-- | drivers/net/vxlan.c | 73 |
1 files changed, 30 insertions, 43 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 97a306c9e65d..916a62149a12 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -105,10 +105,8 @@ struct vxlan_fdb { | |||
105 | struct vxlan_dev { | 105 | struct vxlan_dev { |
106 | struct hlist_node hlist; | 106 | struct hlist_node hlist; |
107 | struct net_device *dev; | 107 | struct net_device *dev; |
108 | __u32 vni; /* virtual network id */ | 108 | struct vxlan_rdst default_dst; /* default destination */ |
109 | __be32 gaddr; /* multicast group */ | ||
110 | __be32 saddr; /* source address */ | 109 | __be32 saddr; /* source address */ |
111 | unsigned int link; /* link to multicast over */ | ||
112 | __u16 port_min; /* source port range */ | 110 | __u16 port_min; /* source port range */ |
113 | __u16 port_max; | 111 | __u16 port_max; |
114 | __u8 tos; /* TOS override */ | 112 | __u8 tos; /* TOS override */ |
@@ -146,7 +144,7 @@ static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id) | |||
146 | struct vxlan_dev *vxlan; | 144 | struct vxlan_dev *vxlan; |
147 | 145 | ||
148 | hlist_for_each_entry_rcu(vxlan, vni_head(net, id), hlist) { | 146 | hlist_for_each_entry_rcu(vxlan, vni_head(net, id), hlist) { |
149 | if (vxlan->vni == id) | 147 | if (vxlan->default_dst.remote_vni == id) |
150 | return vxlan; | 148 | return vxlan; |
151 | } | 149 | } |
152 | 150 | ||
@@ -194,7 +192,7 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan, | |||
194 | if (rdst->remote_port && rdst->remote_port != vxlan_port && | 192 | if (rdst->remote_port && rdst->remote_port != vxlan_port && |
195 | nla_put_be16(skb, NDA_PORT, rdst->remote_port)) | 193 | nla_put_be16(skb, NDA_PORT, rdst->remote_port)) |
196 | goto nla_put_failure; | 194 | goto nla_put_failure; |
197 | if (rdst->remote_vni != vxlan->vni && | 195 | if (rdst->remote_vni != vxlan->default_dst.remote_vni && |
198 | nla_put_be32(skb, NDA_VNI, rdst->remote_vni)) | 196 | nla_put_be32(skb, NDA_VNI, rdst->remote_vni)) |
199 | goto nla_put_failure; | 197 | goto nla_put_failure; |
200 | if (rdst->remote_ifindex && | 198 | if (rdst->remote_ifindex && |
@@ -465,7 +463,7 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], | |||
465 | return -EINVAL; | 463 | return -EINVAL; |
466 | vni = nla_get_u32(tb[NDA_VNI]); | 464 | vni = nla_get_u32(tb[NDA_VNI]); |
467 | } else | 465 | } else |
468 | vni = vxlan->vni; | 466 | vni = vxlan->default_dst.remote_vni; |
469 | 467 | ||
470 | if (tb[NDA_IFINDEX]) { | 468 | if (tb[NDA_IFINDEX]) { |
471 | struct net_device *tdev; | 469 | struct net_device *tdev; |
@@ -570,7 +568,7 @@ static void vxlan_snoop(struct net_device *dev, | |||
570 | err = vxlan_fdb_create(vxlan, src_mac, src_ip, | 568 | err = vxlan_fdb_create(vxlan, src_mac, src_ip, |
571 | NUD_REACHABLE, | 569 | NUD_REACHABLE, |
572 | NLM_F_EXCL|NLM_F_CREATE, | 570 | NLM_F_EXCL|NLM_F_CREATE, |
573 | vxlan_port, vxlan->vni, 0); | 571 | vxlan_port, vxlan->default_dst.remote_vni, 0); |
574 | spin_unlock(&vxlan->hash_lock); | 572 | spin_unlock(&vxlan->hash_lock); |
575 | } | 573 | } |
576 | } | 574 | } |
@@ -591,7 +589,7 @@ static bool vxlan_group_used(struct vxlan_net *vn, | |||
591 | if (!netif_running(vxlan->dev)) | 589 | if (!netif_running(vxlan->dev)) |
592 | continue; | 590 | continue; |
593 | 591 | ||
594 | if (vxlan->gaddr == this->gaddr) | 592 | if (vxlan->default_dst.remote_ip == this->default_dst.remote_ip) |
595 | return true; | 593 | return true; |
596 | } | 594 | } |
597 | 595 | ||
@@ -605,8 +603,8 @@ static int vxlan_join_group(struct net_device *dev) | |||
605 | struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); | 603 | struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); |
606 | struct sock *sk = vn->sock->sk; | 604 | struct sock *sk = vn->sock->sk; |
607 | struct ip_mreqn mreq = { | 605 | struct ip_mreqn mreq = { |
608 | .imr_multiaddr.s_addr = vxlan->gaddr, | 606 | .imr_multiaddr.s_addr = vxlan->default_dst.remote_ip, |
609 | .imr_ifindex = vxlan->link, | 607 | .imr_ifindex = vxlan->default_dst.remote_ifindex, |
610 | }; | 608 | }; |
611 | int err; | 609 | int err; |
612 | 610 | ||
@@ -633,8 +631,8 @@ static int vxlan_leave_group(struct net_device *dev) | |||
633 | int err = 0; | 631 | int err = 0; |
634 | struct sock *sk = vn->sock->sk; | 632 | struct sock *sk = vn->sock->sk; |
635 | struct ip_mreqn mreq = { | 633 | struct ip_mreqn mreq = { |
636 | .imr_multiaddr.s_addr = vxlan->gaddr, | 634 | .imr_multiaddr.s_addr = vxlan->default_dst.remote_ip, |
637 | .imr_ifindex = vxlan->link, | 635 | .imr_ifindex = vxlan->default_dst.remote_ifindex, |
638 | }; | 636 | }; |
639 | 637 | ||
640 | /* Only leave group when last vxlan is done. */ | 638 | /* Only leave group when last vxlan is done. */ |
@@ -1091,7 +1089,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1091 | struct vxlan_dev *vxlan = netdev_priv(dev); | 1089 | struct vxlan_dev *vxlan = netdev_priv(dev); |
1092 | struct ethhdr *eth; | 1090 | struct ethhdr *eth; |
1093 | bool did_rsc = false; | 1091 | bool did_rsc = false; |
1094 | struct vxlan_rdst group, *rdst0, *rdst; | 1092 | struct vxlan_rdst *rdst0, *rdst; |
1095 | struct vxlan_fdb *f; | 1093 | struct vxlan_fdb *f; |
1096 | int rc1, rc; | 1094 | int rc1, rc; |
1097 | 1095 | ||
@@ -1106,14 +1104,9 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1106 | f = vxlan_find_mac(vxlan, eth->h_dest); | 1104 | f = vxlan_find_mac(vxlan, eth->h_dest); |
1107 | if (f == NULL) { | 1105 | if (f == NULL) { |
1108 | did_rsc = false; | 1106 | did_rsc = false; |
1109 | group.remote_port = vxlan_port; | 1107 | rdst0 = &vxlan->default_dst; |
1110 | group.remote_vni = vxlan->vni; | 1108 | |
1111 | group.remote_ip = vxlan->gaddr; | 1109 | if (rdst0->remote_ip == htonl(INADDR_ANY) && |
1112 | group.remote_ifindex = vxlan->link; | ||
1113 | group.remote_next = NULL; | ||
1114 | rdst0 = &group; | ||
1115 | |||
1116 | if (group.remote_ip == htonl(INADDR_ANY) && | ||
1117 | (vxlan->flags & VXLAN_F_L2MISS) && | 1110 | (vxlan->flags & VXLAN_F_L2MISS) && |
1118 | !is_multicast_ether_addr(eth->h_dest)) | 1111 | !is_multicast_ether_addr(eth->h_dest)) |
1119 | vxlan_fdb_miss(vxlan, eth->h_dest); | 1112 | vxlan_fdb_miss(vxlan, eth->h_dest); |
@@ -1191,7 +1184,7 @@ static int vxlan_open(struct net_device *dev) | |||
1191 | struct vxlan_dev *vxlan = netdev_priv(dev); | 1184 | struct vxlan_dev *vxlan = netdev_priv(dev); |
1192 | int err; | 1185 | int err; |
1193 | 1186 | ||
1194 | if (vxlan->gaddr) { | 1187 | if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip))) { |
1195 | err = vxlan_join_group(dev); | 1188 | err = vxlan_join_group(dev); |
1196 | if (err) | 1189 | if (err) |
1197 | return err; | 1190 | return err; |
@@ -1225,7 +1218,7 @@ static int vxlan_stop(struct net_device *dev) | |||
1225 | { | 1218 | { |
1226 | struct vxlan_dev *vxlan = netdev_priv(dev); | 1219 | struct vxlan_dev *vxlan = netdev_priv(dev); |
1227 | 1220 | ||
1228 | if (vxlan->gaddr) | 1221 | if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip))) |
1229 | vxlan_leave_group(dev); | 1222 | vxlan_leave_group(dev); |
1230 | 1223 | ||
1231 | del_timer_sync(&vxlan->age_timer); | 1224 | del_timer_sync(&vxlan->age_timer); |
@@ -1311,7 +1304,7 @@ static void vxlan_setup(struct net_device *dev) | |||
1311 | 1304 | ||
1312 | static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { | 1305 | static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { |
1313 | [IFLA_VXLAN_ID] = { .type = NLA_U32 }, | 1306 | [IFLA_VXLAN_ID] = { .type = NLA_U32 }, |
1314 | [IFLA_VXLAN_GROUP] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, | 1307 | [IFLA_VXLAN_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, |
1315 | [IFLA_VXLAN_LINK] = { .type = NLA_U32 }, | 1308 | [IFLA_VXLAN_LINK] = { .type = NLA_U32 }, |
1316 | [IFLA_VXLAN_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) }, | 1309 | [IFLA_VXLAN_LOCAL] = { .len = FIELD_SIZEOF(struct iphdr, saddr) }, |
1317 | [IFLA_VXLAN_TOS] = { .type = NLA_U8 }, | 1310 | [IFLA_VXLAN_TOS] = { .type = NLA_U8 }, |
@@ -1349,14 +1342,6 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) | |||
1349 | return -ERANGE; | 1342 | return -ERANGE; |
1350 | } | 1343 | } |
1351 | 1344 | ||
1352 | if (data[IFLA_VXLAN_GROUP]) { | ||
1353 | __be32 gaddr = nla_get_be32(data[IFLA_VXLAN_GROUP]); | ||
1354 | if (!IN_MULTICAST(ntohl(gaddr))) { | ||
1355 | pr_debug("group address is not IPv4 multicast\n"); | ||
1356 | return -EADDRNOTAVAIL; | ||
1357 | } | ||
1358 | } | ||
1359 | |||
1360 | if (data[IFLA_VXLAN_PORT_RANGE]) { | 1345 | if (data[IFLA_VXLAN_PORT_RANGE]) { |
1361 | const struct ifla_vxlan_port_range *p | 1346 | const struct ifla_vxlan_port_range *p |
1362 | = nla_data(data[IFLA_VXLAN_PORT_RANGE]); | 1347 | = nla_data(data[IFLA_VXLAN_PORT_RANGE]); |
@@ -1387,6 +1372,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, | |||
1387 | struct nlattr *tb[], struct nlattr *data[]) | 1372 | struct nlattr *tb[], struct nlattr *data[]) |
1388 | { | 1373 | { |
1389 | struct vxlan_dev *vxlan = netdev_priv(dev); | 1374 | struct vxlan_dev *vxlan = netdev_priv(dev); |
1375 | struct vxlan_rdst *dst = &vxlan->default_dst; | ||
1390 | __u32 vni; | 1376 | __u32 vni; |
1391 | int err; | 1377 | int err; |
1392 | 1378 | ||
@@ -1398,21 +1384,21 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, | |||
1398 | pr_info("duplicate VNI %u\n", vni); | 1384 | pr_info("duplicate VNI %u\n", vni); |
1399 | return -EEXIST; | 1385 | return -EEXIST; |
1400 | } | 1386 | } |
1401 | vxlan->vni = vni; | 1387 | dst->remote_vni = vni; |
1402 | 1388 | ||
1403 | if (data[IFLA_VXLAN_GROUP]) | 1389 | if (data[IFLA_VXLAN_REMOTE]) |
1404 | vxlan->gaddr = nla_get_be32(data[IFLA_VXLAN_GROUP]); | 1390 | dst->remote_ip = nla_get_be32(data[IFLA_VXLAN_REMOTE]); |
1405 | 1391 | ||
1406 | if (data[IFLA_VXLAN_LOCAL]) | 1392 | if (data[IFLA_VXLAN_LOCAL]) |
1407 | vxlan->saddr = nla_get_be32(data[IFLA_VXLAN_LOCAL]); | 1393 | vxlan->saddr = nla_get_be32(data[IFLA_VXLAN_LOCAL]); |
1408 | 1394 | ||
1409 | if (data[IFLA_VXLAN_LINK] && | 1395 | if (data[IFLA_VXLAN_LINK] && |
1410 | (vxlan->link = nla_get_u32(data[IFLA_VXLAN_LINK]))) { | 1396 | (dst->remote_ifindex = nla_get_u32(data[IFLA_VXLAN_LINK]))) { |
1411 | struct net_device *lowerdev | 1397 | struct net_device *lowerdev |
1412 | = __dev_get_by_index(net, vxlan->link); | 1398 | = __dev_get_by_index(net, dst->remote_ifindex); |
1413 | 1399 | ||
1414 | if (!lowerdev) { | 1400 | if (!lowerdev) { |
1415 | pr_info("ifindex %d does not exist\n", vxlan->link); | 1401 | pr_info("ifindex %d does not exist\n", dst->remote_ifindex); |
1416 | return -ENODEV; | 1402 | return -ENODEV; |
1417 | } | 1403 | } |
1418 | 1404 | ||
@@ -1464,7 +1450,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, | |||
1464 | 1450 | ||
1465 | err = register_netdevice(dev); | 1451 | err = register_netdevice(dev); |
1466 | if (!err) | 1452 | if (!err) |
1467 | hlist_add_head_rcu(&vxlan->hlist, vni_head(net, vxlan->vni)); | 1453 | hlist_add_head_rcu(&vxlan->hlist, vni_head(net, dst->remote_vni)); |
1468 | 1454 | ||
1469 | return err; | 1455 | return err; |
1470 | } | 1456 | } |
@@ -1482,7 +1468,7 @@ static size_t vxlan_get_size(const struct net_device *dev) | |||
1482 | { | 1468 | { |
1483 | 1469 | ||
1484 | return nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_ID */ | 1470 | return nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_ID */ |
1485 | nla_total_size(sizeof(__be32)) +/* IFLA_VXLAN_GROUP */ | 1471 | nla_total_size(sizeof(__be32)) +/* IFLA_VXLAN_REMOTE */ |
1486 | nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LINK */ | 1472 | nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LINK */ |
1487 | nla_total_size(sizeof(__be32))+ /* IFLA_VXLAN_LOCAL */ | 1473 | nla_total_size(sizeof(__be32))+ /* IFLA_VXLAN_LOCAL */ |
1488 | nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TTL */ | 1474 | nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TTL */ |
@@ -1501,18 +1487,19 @@ static size_t vxlan_get_size(const struct net_device *dev) | |||
1501 | static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) | 1487 | static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) |
1502 | { | 1488 | { |
1503 | const struct vxlan_dev *vxlan = netdev_priv(dev); | 1489 | const struct vxlan_dev *vxlan = netdev_priv(dev); |
1490 | const struct vxlan_rdst *dst = &vxlan->default_dst; | ||
1504 | struct ifla_vxlan_port_range ports = { | 1491 | struct ifla_vxlan_port_range ports = { |
1505 | .low = htons(vxlan->port_min), | 1492 | .low = htons(vxlan->port_min), |
1506 | .high = htons(vxlan->port_max), | 1493 | .high = htons(vxlan->port_max), |
1507 | }; | 1494 | }; |
1508 | 1495 | ||
1509 | if (nla_put_u32(skb, IFLA_VXLAN_ID, vxlan->vni)) | 1496 | if (nla_put_u32(skb, IFLA_VXLAN_ID, dst->remote_vni)) |
1510 | goto nla_put_failure; | 1497 | goto nla_put_failure; |
1511 | 1498 | ||
1512 | if (vxlan->gaddr && nla_put_be32(skb, IFLA_VXLAN_GROUP, vxlan->gaddr)) | 1499 | if (dst->remote_ip && nla_put_be32(skb, IFLA_VXLAN_REMOTE, dst->remote_ip)) |
1513 | goto nla_put_failure; | 1500 | goto nla_put_failure; |
1514 | 1501 | ||
1515 | if (vxlan->link && nla_put_u32(skb, IFLA_VXLAN_LINK, vxlan->link)) | 1502 | if (dst->remote_ifindex && nla_put_u32(skb, IFLA_VXLAN_LINK, dst->remote_ifindex)) |
1516 | goto nla_put_failure; | 1503 | goto nla_put_failure; |
1517 | 1504 | ||
1518 | if (vxlan->saddr && nla_put_be32(skb, IFLA_VXLAN_LOCAL, vxlan->saddr)) | 1505 | if (vxlan->saddr && nla_put_be32(skb, IFLA_VXLAN_LOCAL, vxlan->saddr)) |