Loading drivers/net/vxlan.c +49 −19 Original line number Diff line number Diff line Loading @@ -80,6 +80,8 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); static int vxlan_net_id; static const u8 all_zeros_mac[ETH_ALEN]; /* per UDP socket information */ struct vxlan_sock { struct hlist_node hlist; Loading Loading @@ -1151,7 +1153,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) struct vxlan_dev *vxlan = netdev_priv(dev); struct ethhdr *eth; bool did_rsc = false; struct vxlan_rdst *rdst0, *rdst; struct vxlan_rdst *rdst; struct vxlan_fdb *f; skb_reset_mac_header(skb); Loading @@ -1171,26 +1173,27 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) } if (f == NULL) { rdst0 = &vxlan->default_dst; if (rdst0->remote_ip == htonl(INADDR_ANY) && (vxlan->flags & VXLAN_F_L2MISS) && f = vxlan_find_mac(vxlan, all_zeros_mac); if (f == NULL) { if ((vxlan->flags & VXLAN_F_L2MISS) && !is_multicast_ether_addr(eth->h_dest)) vxlan_fdb_miss(vxlan, eth->h_dest); } else { rdst = rdst0 = first_remote(f); /* if there are multiple destinations, send copies */ list_for_each_entry_continue_rcu(rdst, &f->remotes, list) { dev->stats.tx_dropped++; dev_kfree_skb(skb); return NETDEV_TX_OK; } } list_for_each_entry_rcu(rdst, &f->remotes, list) { struct sk_buff *skb1; skb1 = skb_clone(skb, GFP_ATOMIC); if (skb1) vxlan_xmit_one(skb1, dev, rdst, did_rsc); } } vxlan_xmit_one(skb, dev, rdst0, did_rsc); dev_kfree_skb(skb); return NETDEV_TX_OK; } Loading Loading @@ -1260,12 +1263,25 @@ static int vxlan_init(struct net_device *dev) return 0; } static void vxlan_fdb_delete_defualt(struct vxlan_dev *vxlan) { struct vxlan_fdb *f; spin_lock_bh(&vxlan->hash_lock); f = __vxlan_find_mac(vxlan, all_zeros_mac); if (f) vxlan_fdb_destroy(vxlan, f); spin_unlock_bh(&vxlan->hash_lock); } static void vxlan_uninit(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); struct vxlan_sock *vs = vxlan->vn_sock; vxlan_fdb_delete_defualt(vxlan); if (vs) vxlan_sock_release(vn, vs); free_percpu(dev->tstats); Loading Loading @@ -1304,6 +1320,8 @@ static void vxlan_flush(struct vxlan_dev *vxlan) hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { struct vxlan_fdb *f = container_of(p, struct vxlan_fdb, hlist); /* the all_zeros_mac entry is deleted at vxlan_uninit */ if (!is_zero_ether_addr(f->eth_addr)) vxlan_fdb_destroy(vxlan, f); } } Loading Loading @@ -1657,10 +1675,22 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, SET_ETHTOOL_OPS(dev, &vxlan_ethtool_ops); err = register_netdevice(dev); /* create an fdb entry for default destination */ err = vxlan_fdb_create(vxlan, all_zeros_mac, vxlan->default_dst.remote_ip, NUD_REACHABLE|NUD_PERMANENT, NLM_F_EXCL|NLM_F_CREATE, vxlan->dst_port, vxlan->default_dst.remote_vni, vxlan->default_dst.remote_ifindex, NTF_SELF); if (err) return err; err = register_netdevice(dev); if (err) { vxlan_fdb_delete_defualt(vxlan); return err; } list_add(&vxlan->next, &vn->vxlan_list); return 0; Loading Loading
drivers/net/vxlan.c +49 −19 Original line number Diff line number Diff line Loading @@ -80,6 +80,8 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); static int vxlan_net_id; static const u8 all_zeros_mac[ETH_ALEN]; /* per UDP socket information */ struct vxlan_sock { struct hlist_node hlist; Loading Loading @@ -1151,7 +1153,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) struct vxlan_dev *vxlan = netdev_priv(dev); struct ethhdr *eth; bool did_rsc = false; struct vxlan_rdst *rdst0, *rdst; struct vxlan_rdst *rdst; struct vxlan_fdb *f; skb_reset_mac_header(skb); Loading @@ -1171,26 +1173,27 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) } if (f == NULL) { rdst0 = &vxlan->default_dst; if (rdst0->remote_ip == htonl(INADDR_ANY) && (vxlan->flags & VXLAN_F_L2MISS) && f = vxlan_find_mac(vxlan, all_zeros_mac); if (f == NULL) { if ((vxlan->flags & VXLAN_F_L2MISS) && !is_multicast_ether_addr(eth->h_dest)) vxlan_fdb_miss(vxlan, eth->h_dest); } else { rdst = rdst0 = first_remote(f); /* if there are multiple destinations, send copies */ list_for_each_entry_continue_rcu(rdst, &f->remotes, list) { dev->stats.tx_dropped++; dev_kfree_skb(skb); return NETDEV_TX_OK; } } list_for_each_entry_rcu(rdst, &f->remotes, list) { struct sk_buff *skb1; skb1 = skb_clone(skb, GFP_ATOMIC); if (skb1) vxlan_xmit_one(skb1, dev, rdst, did_rsc); } } vxlan_xmit_one(skb, dev, rdst0, did_rsc); dev_kfree_skb(skb); return NETDEV_TX_OK; } Loading Loading @@ -1260,12 +1263,25 @@ static int vxlan_init(struct net_device *dev) return 0; } static void vxlan_fdb_delete_defualt(struct vxlan_dev *vxlan) { struct vxlan_fdb *f; spin_lock_bh(&vxlan->hash_lock); f = __vxlan_find_mac(vxlan, all_zeros_mac); if (f) vxlan_fdb_destroy(vxlan, f); spin_unlock_bh(&vxlan->hash_lock); } static void vxlan_uninit(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); struct vxlan_sock *vs = vxlan->vn_sock; vxlan_fdb_delete_defualt(vxlan); if (vs) vxlan_sock_release(vn, vs); free_percpu(dev->tstats); Loading Loading @@ -1304,6 +1320,8 @@ static void vxlan_flush(struct vxlan_dev *vxlan) hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { struct vxlan_fdb *f = container_of(p, struct vxlan_fdb, hlist); /* the all_zeros_mac entry is deleted at vxlan_uninit */ if (!is_zero_ether_addr(f->eth_addr)) vxlan_fdb_destroy(vxlan, f); } } Loading Loading @@ -1657,10 +1675,22 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, SET_ETHTOOL_OPS(dev, &vxlan_ethtool_ops); err = register_netdevice(dev); /* create an fdb entry for default destination */ err = vxlan_fdb_create(vxlan, all_zeros_mac, vxlan->default_dst.remote_ip, NUD_REACHABLE|NUD_PERMANENT, NLM_F_EXCL|NLM_F_CREATE, vxlan->dst_port, vxlan->default_dst.remote_vni, vxlan->default_dst.remote_ifindex, NTF_SELF); if (err) return err; err = register_netdevice(dev); if (err) { vxlan_fdb_delete_defualt(vxlan); return err; } list_add(&vxlan->next, &vn->vxlan_list); return 0; Loading