diff options
author | Mike Rapoport <mike.rapoport@ravellosystems.com> | 2013-06-25 09:01:51 -0400 |
---|---|---|
committer | Stephen Hemminger <stephen@networkplumber.org> | 2013-06-25 12:31:35 -0400 |
commit | afbd8bae9c798c5cdbe4439d3a50536b5438247c (patch) | |
tree | a92d4af5b7c0a335f6c2a2d55d554542801b2822 | |
parent | 60d9d4c6dbd1bad80fb9a77775fc704302a563c9 (diff) |
vxlan: add implicit fdb entry for default destination
Signed-off-by: Mike Rapoport <mike.rapoport@ravellosystems.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
-rw-r--r-- | drivers/net/vxlan.c | 68 |
1 files changed, 49 insertions, 19 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 212a25601fa6..bdfe46e50c49 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -80,6 +80,8 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); | |||
80 | 80 | ||
81 | static int vxlan_net_id; | 81 | static int vxlan_net_id; |
82 | 82 | ||
83 | static const u8 all_zeros_mac[ETH_ALEN]; | ||
84 | |||
83 | /* per UDP socket information */ | 85 | /* per UDP socket information */ |
84 | struct vxlan_sock { | 86 | struct vxlan_sock { |
85 | struct hlist_node hlist; | 87 | struct hlist_node hlist; |
@@ -1151,7 +1153,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1151 | struct vxlan_dev *vxlan = netdev_priv(dev); | 1153 | struct vxlan_dev *vxlan = netdev_priv(dev); |
1152 | struct ethhdr *eth; | 1154 | struct ethhdr *eth; |
1153 | bool did_rsc = false; | 1155 | bool did_rsc = false; |
1154 | struct vxlan_rdst *rdst0, *rdst; | 1156 | struct vxlan_rdst *rdst; |
1155 | struct vxlan_fdb *f; | 1157 | struct vxlan_fdb *f; |
1156 | 1158 | ||
1157 | skb_reset_mac_header(skb); | 1159 | skb_reset_mac_header(skb); |
@@ -1171,26 +1173,27 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1171 | } | 1173 | } |
1172 | 1174 | ||
1173 | if (f == NULL) { | 1175 | if (f == NULL) { |
1174 | rdst0 = &vxlan->default_dst; | 1176 | f = vxlan_find_mac(vxlan, all_zeros_mac); |
1175 | 1177 | if (f == NULL) { | |
1176 | if (rdst0->remote_ip == htonl(INADDR_ANY) && | 1178 | if ((vxlan->flags & VXLAN_F_L2MISS) && |
1177 | (vxlan->flags & VXLAN_F_L2MISS) && | 1179 | !is_multicast_ether_addr(eth->h_dest)) |
1178 | !is_multicast_ether_addr(eth->h_dest)) | 1180 | vxlan_fdb_miss(vxlan, eth->h_dest); |
1179 | vxlan_fdb_miss(vxlan, eth->h_dest); | 1181 | |
1180 | } else { | 1182 | dev->stats.tx_dropped++; |
1181 | rdst = rdst0 = first_remote(f); | 1183 | dev_kfree_skb(skb); |
1184 | return NETDEV_TX_OK; | ||
1185 | } | ||
1186 | } | ||
1182 | 1187 | ||
1183 | /* if there are multiple destinations, send copies */ | 1188 | list_for_each_entry_rcu(rdst, &f->remotes, list) { |
1184 | list_for_each_entry_continue_rcu(rdst, &f->remotes, list) { | 1189 | struct sk_buff *skb1; |
1185 | struct sk_buff *skb1; | ||
1186 | 1190 | ||
1187 | skb1 = skb_clone(skb, GFP_ATOMIC); | 1191 | skb1 = skb_clone(skb, GFP_ATOMIC); |
1188 | if (skb1) | 1192 | if (skb1) |
1189 | vxlan_xmit_one(skb1, dev, rdst, did_rsc); | 1193 | vxlan_xmit_one(skb1, dev, rdst, did_rsc); |
1190 | } | ||
1191 | } | 1194 | } |
1192 | 1195 | ||
1193 | vxlan_xmit_one(skb, dev, rdst0, did_rsc); | 1196 | dev_kfree_skb(skb); |
1194 | return NETDEV_TX_OK; | 1197 | return NETDEV_TX_OK; |
1195 | } | 1198 | } |
1196 | 1199 | ||
@@ -1260,12 +1263,25 @@ static int vxlan_init(struct net_device *dev) | |||
1260 | return 0; | 1263 | return 0; |
1261 | } | 1264 | } |
1262 | 1265 | ||
1266 | static void vxlan_fdb_delete_defualt(struct vxlan_dev *vxlan) | ||
1267 | { | ||
1268 | struct vxlan_fdb *f; | ||
1269 | |||
1270 | spin_lock_bh(&vxlan->hash_lock); | ||
1271 | f = __vxlan_find_mac(vxlan, all_zeros_mac); | ||
1272 | if (f) | ||
1273 | vxlan_fdb_destroy(vxlan, f); | ||
1274 | spin_unlock_bh(&vxlan->hash_lock); | ||
1275 | } | ||
1276 | |||
1263 | static void vxlan_uninit(struct net_device *dev) | 1277 | static void vxlan_uninit(struct net_device *dev) |
1264 | { | 1278 | { |
1265 | struct vxlan_dev *vxlan = netdev_priv(dev); | 1279 | struct vxlan_dev *vxlan = netdev_priv(dev); |
1266 | struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); | 1280 | struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); |
1267 | struct vxlan_sock *vs = vxlan->vn_sock; | 1281 | struct vxlan_sock *vs = vxlan->vn_sock; |
1268 | 1282 | ||
1283 | vxlan_fdb_delete_defualt(vxlan); | ||
1284 | |||
1269 | if (vs) | 1285 | if (vs) |
1270 | vxlan_sock_release(vn, vs); | 1286 | vxlan_sock_release(vn, vs); |
1271 | free_percpu(dev->tstats); | 1287 | free_percpu(dev->tstats); |
@@ -1304,7 +1320,9 @@ static void vxlan_flush(struct vxlan_dev *vxlan) | |||
1304 | hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { | 1320 | hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { |
1305 | struct vxlan_fdb *f | 1321 | struct vxlan_fdb *f |
1306 | = container_of(p, struct vxlan_fdb, hlist); | 1322 | = container_of(p, struct vxlan_fdb, hlist); |
1307 | vxlan_fdb_destroy(vxlan, f); | 1323 | /* the all_zeros_mac entry is deleted at vxlan_uninit */ |
1324 | if (!is_zero_ether_addr(f->eth_addr)) | ||
1325 | vxlan_fdb_destroy(vxlan, f); | ||
1308 | } | 1326 | } |
1309 | } | 1327 | } |
1310 | spin_unlock_bh(&vxlan->hash_lock); | 1328 | spin_unlock_bh(&vxlan->hash_lock); |
@@ -1657,10 +1675,22 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, | |||
1657 | 1675 | ||
1658 | SET_ETHTOOL_OPS(dev, &vxlan_ethtool_ops); | 1676 | SET_ETHTOOL_OPS(dev, &vxlan_ethtool_ops); |
1659 | 1677 | ||
1660 | err = register_netdevice(dev); | 1678 | /* create an fdb entry for default destination */ |
1679 | err = vxlan_fdb_create(vxlan, all_zeros_mac, | ||
1680 | vxlan->default_dst.remote_ip, | ||
1681 | NUD_REACHABLE|NUD_PERMANENT, | ||
1682 | NLM_F_EXCL|NLM_F_CREATE, | ||
1683 | vxlan->dst_port, vxlan->default_dst.remote_vni, | ||
1684 | vxlan->default_dst.remote_ifindex, NTF_SELF); | ||
1661 | if (err) | 1685 | if (err) |
1662 | return err; | 1686 | return err; |
1663 | 1687 | ||
1688 | err = register_netdevice(dev); | ||
1689 | if (err) { | ||
1690 | vxlan_fdb_delete_defualt(vxlan); | ||
1691 | return err; | ||
1692 | } | ||
1693 | |||
1664 | list_add(&vxlan->next, &vn->vxlan_list); | 1694 | list_add(&vxlan->next, &vn->vxlan_list); |
1665 | 1695 | ||
1666 | return 0; | 1696 | return 0; |