1243a2e63SVlad Yasevich #include <linux/kernel.h> 2243a2e63SVlad Yasevich #include <linux/netdevice.h> 3243a2e63SVlad Yasevich #include <linux/rtnetlink.h> 4243a2e63SVlad Yasevich #include <linux/slab.h> 57f109539SScott Feldman #include <net/switchdev.h> 6243a2e63SVlad Yasevich 7243a2e63SVlad Yasevich #include "br_private.h" 8243a2e63SVlad Yasevich 92594e906SNikolay Aleksandrov static inline int br_vlan_cmp(struct rhashtable_compare_arg *arg, 102594e906SNikolay Aleksandrov const void *ptr) 11552406c4SVlad Yasevich { 122594e906SNikolay Aleksandrov const struct net_bridge_vlan *vle = ptr; 132594e906SNikolay Aleksandrov u16 vid = *(u16 *)arg->key; 142594e906SNikolay Aleksandrov 152594e906SNikolay Aleksandrov return vle->vid != vid; 162594e906SNikolay Aleksandrov } 172594e906SNikolay Aleksandrov 182594e906SNikolay Aleksandrov static const struct rhashtable_params br_vlan_rht_params = { 192594e906SNikolay Aleksandrov .head_offset = offsetof(struct net_bridge_vlan, vnode), 202594e906SNikolay Aleksandrov .key_offset = offsetof(struct net_bridge_vlan, vid), 212594e906SNikolay Aleksandrov .key_len = sizeof(u16), 228af78b64SNikolay Aleksandrov .nelem_hint = 3, 238af78b64SNikolay Aleksandrov .locks_mul = 1, 242594e906SNikolay Aleksandrov .max_size = VLAN_N_VID, 252594e906SNikolay Aleksandrov .obj_cmpfn = br_vlan_cmp, 262594e906SNikolay Aleksandrov .automatic_shrinking = true, 272594e906SNikolay Aleksandrov }; 282594e906SNikolay Aleksandrov 292594e906SNikolay Aleksandrov static struct net_bridge_vlan *br_vlan_lookup(struct rhashtable *tbl, u16 vid) 302594e906SNikolay Aleksandrov { 312594e906SNikolay Aleksandrov return rhashtable_lookup_fast(tbl, &vid, br_vlan_rht_params); 322594e906SNikolay Aleksandrov } 332594e906SNikolay Aleksandrov 3477751ee8SNikolay Aleksandrov static void __vlan_add_pvid(struct net_bridge_vlan_group *vg, u16 vid) 352594e906SNikolay Aleksandrov { 3677751ee8SNikolay Aleksandrov if (vg->pvid == vid) 37552406c4SVlad Yasevich return; 38552406c4SVlad Yasevich 39552406c4SVlad Yasevich smp_wmb(); 4077751ee8SNikolay Aleksandrov vg->pvid = vid; 41552406c4SVlad Yasevich } 42552406c4SVlad Yasevich 4377751ee8SNikolay Aleksandrov static void __vlan_delete_pvid(struct net_bridge_vlan_group *vg, u16 vid) 44552406c4SVlad Yasevich { 4577751ee8SNikolay Aleksandrov if (vg->pvid != vid) 46552406c4SVlad Yasevich return; 47552406c4SVlad Yasevich 48552406c4SVlad Yasevich smp_wmb(); 4977751ee8SNikolay Aleksandrov vg->pvid = 0; 50552406c4SVlad Yasevich } 51552406c4SVlad Yasevich 522594e906SNikolay Aleksandrov static void __vlan_add_flags(struct net_bridge_vlan *v, u16 flags) 5335e03f3aSVlad Yasevich { 5477751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 5577751ee8SNikolay Aleksandrov 562594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) 57907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 58635126b7SVlad Yasevich else 59907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 6077751ee8SNikolay Aleksandrov 6177751ee8SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_PVID) 6277751ee8SNikolay Aleksandrov __vlan_add_pvid(vg, v->vid); 632594e906SNikolay Aleksandrov else 6477751ee8SNikolay Aleksandrov __vlan_delete_pvid(vg, v->vid); 6535e03f3aSVlad Yasevich 6635e03f3aSVlad Yasevich if (flags & BRIDGE_VLAN_INFO_UNTAGGED) 672594e906SNikolay Aleksandrov v->flags |= BRIDGE_VLAN_INFO_UNTAGGED; 68635126b7SVlad Yasevich else 692594e906SNikolay Aleksandrov v->flags &= ~BRIDGE_VLAN_INFO_UNTAGGED; 7035e03f3aSVlad Yasevich } 7135e03f3aSVlad Yasevich 727f109539SScott Feldman static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br, 737f109539SScott Feldman u16 vid, u16 flags) 747f109539SScott Feldman { 758f24f309SJiri Pirko struct switchdev_obj_port_vlan v = { 766ff64f6fSIdo Schimmel .obj.orig_dev = dev, 779e8f4a54SJiri Pirko .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, 787f109539SScott Feldman .flags = flags, 793e3a78b4SScott Feldman .vid_begin = vid, 807f109539SScott Feldman .vid_end = vid, 817f109539SScott Feldman }; 820944d6b5SJiri Pirko int err; 837f109539SScott Feldman 840944d6b5SJiri Pirko /* Try switchdev op first. In case it is not supported, fallback to 850944d6b5SJiri Pirko * 8021q add. 860944d6b5SJiri Pirko */ 879e8f4a54SJiri Pirko err = switchdev_port_obj_add(dev, &v.obj); 887f109539SScott Feldman if (err == -EOPNOTSUPP) 890944d6b5SJiri Pirko return vlan_vid_add(dev, br->vlan_proto, vid); 907f109539SScott Feldman return err; 917f109539SScott Feldman } 927f109539SScott Feldman 932594e906SNikolay Aleksandrov static void __vlan_add_list(struct net_bridge_vlan *v) 94243a2e63SVlad Yasevich { 95907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 962594e906SNikolay Aleksandrov struct list_head *headp, *hpos; 972594e906SNikolay Aleksandrov struct net_bridge_vlan *vent; 98243a2e63SVlad Yasevich 99907b1e6eSNikolay Aleksandrov if (br_vlan_is_master(v)) 100907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 101907b1e6eSNikolay Aleksandrov else 102907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 103907b1e6eSNikolay Aleksandrov 104907b1e6eSNikolay Aleksandrov headp = &vg->vlan_list; 1052594e906SNikolay Aleksandrov list_for_each_prev(hpos, headp) { 1062594e906SNikolay Aleksandrov vent = list_entry(hpos, struct net_bridge_vlan, vlist); 1072594e906SNikolay Aleksandrov if (v->vid < vent->vid) 1082594e906SNikolay Aleksandrov continue; 1092594e906SNikolay Aleksandrov else 1102594e906SNikolay Aleksandrov break; 1112594e906SNikolay Aleksandrov } 112586c2b57SNikolay Aleksandrov list_add_rcu(&v->vlist, hpos); 113552406c4SVlad Yasevich } 114243a2e63SVlad Yasevich 1152594e906SNikolay Aleksandrov static void __vlan_del_list(struct net_bridge_vlan *v) 1162594e906SNikolay Aleksandrov { 117586c2b57SNikolay Aleksandrov list_del_rcu(&v->vlist); 118243a2e63SVlad Yasevich } 119243a2e63SVlad Yasevich 120bf361ad3SVivien Didelot static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br, 1217f109539SScott Feldman u16 vid) 1227f109539SScott Feldman { 1238f24f309SJiri Pirko struct switchdev_obj_port_vlan v = { 1246ff64f6fSIdo Schimmel .obj.orig_dev = dev, 1259e8f4a54SJiri Pirko .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, 1263e3a78b4SScott Feldman .vid_begin = vid, 1277f109539SScott Feldman .vid_end = vid, 1287f109539SScott Feldman }; 1290944d6b5SJiri Pirko int err; 1307f109539SScott Feldman 1310944d6b5SJiri Pirko /* Try switchdev op first. In case it is not supported, fallback to 1320944d6b5SJiri Pirko * 8021q del. 1330944d6b5SJiri Pirko */ 1349e8f4a54SJiri Pirko err = switchdev_port_obj_del(dev, &v.obj); 1350944d6b5SJiri Pirko if (err == -EOPNOTSUPP) { 1360944d6b5SJiri Pirko vlan_vid_del(dev, br->vlan_proto, vid); 1370944d6b5SJiri Pirko return 0; 1387f109539SScott Feldman } 139bf361ad3SVivien Didelot return err; 1407f109539SScott Feldman } 1417f109539SScott Feldman 142f8ed289fSNikolay Aleksandrov /* Returns a master vlan, if it didn't exist it gets created. In all cases a 143f8ed289fSNikolay Aleksandrov * a reference is taken to the master vlan before returning. 144f8ed289fSNikolay Aleksandrov */ 145f8ed289fSNikolay Aleksandrov static struct net_bridge_vlan *br_vlan_get_master(struct net_bridge *br, u16 vid) 146f8ed289fSNikolay Aleksandrov { 147907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 148f8ed289fSNikolay Aleksandrov struct net_bridge_vlan *masterv; 149f8ed289fSNikolay Aleksandrov 150907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 151907b1e6eSNikolay Aleksandrov masterv = br_vlan_find(vg, vid); 152f8ed289fSNikolay Aleksandrov if (!masterv) { 153f8ed289fSNikolay Aleksandrov /* missing global ctx, create it now */ 154f8ed289fSNikolay Aleksandrov if (br_vlan_add(br, vid, 0)) 155f8ed289fSNikolay Aleksandrov return NULL; 156907b1e6eSNikolay Aleksandrov masterv = br_vlan_find(vg, vid); 157f8ed289fSNikolay Aleksandrov if (WARN_ON(!masterv)) 158f8ed289fSNikolay Aleksandrov return NULL; 159f8ed289fSNikolay Aleksandrov } 160f8ed289fSNikolay Aleksandrov atomic_inc(&masterv->refcnt); 161f8ed289fSNikolay Aleksandrov 162f8ed289fSNikolay Aleksandrov return masterv; 163f8ed289fSNikolay Aleksandrov } 164f8ed289fSNikolay Aleksandrov 1656dada9b1SNikolay Aleksandrov static void br_master_vlan_rcu_free(struct rcu_head *rcu) 1666dada9b1SNikolay Aleksandrov { 1676dada9b1SNikolay Aleksandrov struct net_bridge_vlan *v; 1686dada9b1SNikolay Aleksandrov 1696dada9b1SNikolay Aleksandrov v = container_of(rcu, struct net_bridge_vlan, rcu); 1706dada9b1SNikolay Aleksandrov WARN_ON(!br_vlan_is_master(v)); 1716dada9b1SNikolay Aleksandrov free_percpu(v->stats); 1726dada9b1SNikolay Aleksandrov v->stats = NULL; 1736dada9b1SNikolay Aleksandrov kfree(v); 1746dada9b1SNikolay Aleksandrov } 1756dada9b1SNikolay Aleksandrov 176f8ed289fSNikolay Aleksandrov static void br_vlan_put_master(struct net_bridge_vlan *masterv) 177f8ed289fSNikolay Aleksandrov { 178907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 179907b1e6eSNikolay Aleksandrov 180f8ed289fSNikolay Aleksandrov if (!br_vlan_is_master(masterv)) 181f8ed289fSNikolay Aleksandrov return; 182f8ed289fSNikolay Aleksandrov 183907b1e6eSNikolay Aleksandrov vg = br_vlan_group(masterv->br); 184f8ed289fSNikolay Aleksandrov if (atomic_dec_and_test(&masterv->refcnt)) { 185907b1e6eSNikolay Aleksandrov rhashtable_remove_fast(&vg->vlan_hash, 186f8ed289fSNikolay Aleksandrov &masterv->vnode, br_vlan_rht_params); 187f8ed289fSNikolay Aleksandrov __vlan_del_list(masterv); 1886dada9b1SNikolay Aleksandrov call_rcu(&masterv->rcu, br_master_vlan_rcu_free); 189f8ed289fSNikolay Aleksandrov } 190f8ed289fSNikolay Aleksandrov } 191f8ed289fSNikolay Aleksandrov 1922594e906SNikolay Aleksandrov /* This is the shared VLAN add function which works for both ports and bridge 1932594e906SNikolay Aleksandrov * devices. There are four possible calls to this function in terms of the 1942594e906SNikolay Aleksandrov * vlan entry type: 1952594e906SNikolay Aleksandrov * 1. vlan is being added on a port (no master flags, global entry exists) 196ddd611d3SIdo Schimmel * 2. vlan is being added on a bridge (both master and brentry flags) 1972594e906SNikolay Aleksandrov * 3. vlan is being added on a port, but a global entry didn't exist which 198ddd611d3SIdo Schimmel * is being created right now (master flag set, brentry flag unset), the 1992594e906SNikolay Aleksandrov * global entry is used for global per-vlan features, but not for filtering 200ddd611d3SIdo Schimmel * 4. same as 3 but with both master and brentry flags set so the entry 2012594e906SNikolay Aleksandrov * will be used for filtering in both the port and the bridge 2022594e906SNikolay Aleksandrov */ 2032594e906SNikolay Aleksandrov static int __vlan_add(struct net_bridge_vlan *v, u16 flags) 204243a2e63SVlad Yasevich { 2052594e906SNikolay Aleksandrov struct net_bridge_vlan *masterv = NULL; 2062594e906SNikolay Aleksandrov struct net_bridge_port *p = NULL; 2076be144f6SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 2082594e906SNikolay Aleksandrov struct net_device *dev; 2092594e906SNikolay Aleksandrov struct net_bridge *br; 210bf361ad3SVivien Didelot int err; 211bf361ad3SVivien Didelot 2122594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) { 2132594e906SNikolay Aleksandrov br = v->br; 2142594e906SNikolay Aleksandrov dev = br->dev; 215907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 2162594e906SNikolay Aleksandrov } else { 2172594e906SNikolay Aleksandrov p = v->port; 2182594e906SNikolay Aleksandrov br = p->br; 2192594e906SNikolay Aleksandrov dev = p->dev; 220907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 2212594e906SNikolay Aleksandrov } 2222594e906SNikolay Aleksandrov 2232594e906SNikolay Aleksandrov if (p) { 2242594e906SNikolay Aleksandrov /* Add VLAN to the device filter if it is supported. 2252594e906SNikolay Aleksandrov * This ensures tagged traffic enters the bridge when 2262594e906SNikolay Aleksandrov * promiscuous mode is disabled by br_manage_promisc(). 2272594e906SNikolay Aleksandrov */ 2282594e906SNikolay Aleksandrov err = __vlan_vid_add(dev, br, v->vid, flags); 229bf361ad3SVivien Didelot if (err) 2302594e906SNikolay Aleksandrov goto out; 2312594e906SNikolay Aleksandrov 2322594e906SNikolay Aleksandrov /* need to work on the master vlan too */ 2332594e906SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_MASTER) { 2342ffdf508SNikolay Aleksandrov err = br_vlan_add(br, v->vid, flags | 2352ffdf508SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY); 2362594e906SNikolay Aleksandrov if (err) 2372594e906SNikolay Aleksandrov goto out_filt; 2382594e906SNikolay Aleksandrov } 2392594e906SNikolay Aleksandrov 240f8ed289fSNikolay Aleksandrov masterv = br_vlan_get_master(br, v->vid); 241f8ed289fSNikolay Aleksandrov if (!masterv) 2422594e906SNikolay Aleksandrov goto out_filt; 2432594e906SNikolay Aleksandrov v->brvlan = masterv; 2446dada9b1SNikolay Aleksandrov v->stats = masterv->stats; 2452594e906SNikolay Aleksandrov } 2462594e906SNikolay Aleksandrov 2476be144f6SNikolay Aleksandrov /* Add the dev mac and count the vlan only if it's usable */ 2482594e906SNikolay Aleksandrov if (br_vlan_should_use(v)) { 2492594e906SNikolay Aleksandrov err = br_fdb_insert(br, p, dev->dev_addr, v->vid); 2502594e906SNikolay Aleksandrov if (err) { 2512594e906SNikolay Aleksandrov br_err(br, "failed insert local address into bridge forwarding table\n"); 2522594e906SNikolay Aleksandrov goto out_filt; 2532594e906SNikolay Aleksandrov } 2546be144f6SNikolay Aleksandrov vg->num_vlans++; 2552594e906SNikolay Aleksandrov } 2562594e906SNikolay Aleksandrov 2576be144f6SNikolay Aleksandrov err = rhashtable_lookup_insert_fast(&vg->vlan_hash, &v->vnode, 2586be144f6SNikolay Aleksandrov br_vlan_rht_params); 2592594e906SNikolay Aleksandrov if (err) 2602594e906SNikolay Aleksandrov goto out_fdb_insert; 2612594e906SNikolay Aleksandrov 2622594e906SNikolay Aleksandrov __vlan_add_list(v); 2632594e906SNikolay Aleksandrov __vlan_add_flags(v, flags); 2642594e906SNikolay Aleksandrov out: 2652594e906SNikolay Aleksandrov return err; 2662594e906SNikolay Aleksandrov 2672594e906SNikolay Aleksandrov out_fdb_insert: 2686be144f6SNikolay Aleksandrov if (br_vlan_should_use(v)) { 2696be144f6SNikolay Aleksandrov br_fdb_find_delete_local(br, p, dev->dev_addr, v->vid); 2706be144f6SNikolay Aleksandrov vg->num_vlans--; 2716be144f6SNikolay Aleksandrov } 2722594e906SNikolay Aleksandrov 2732594e906SNikolay Aleksandrov out_filt: 2742594e906SNikolay Aleksandrov if (p) { 2752594e906SNikolay Aleksandrov __vlan_vid_del(dev, br, v->vid); 2762594e906SNikolay Aleksandrov if (masterv) { 277f8ed289fSNikolay Aleksandrov br_vlan_put_master(masterv); 2782594e906SNikolay Aleksandrov v->brvlan = NULL; 2792594e906SNikolay Aleksandrov } 2802594e906SNikolay Aleksandrov } 2812594e906SNikolay Aleksandrov 2822594e906SNikolay Aleksandrov goto out; 2832594e906SNikolay Aleksandrov } 2842594e906SNikolay Aleksandrov 2852594e906SNikolay Aleksandrov static int __vlan_del(struct net_bridge_vlan *v) 2862594e906SNikolay Aleksandrov { 2872594e906SNikolay Aleksandrov struct net_bridge_vlan *masterv = v; 28877751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 2892594e906SNikolay Aleksandrov struct net_bridge_port *p = NULL; 2902594e906SNikolay Aleksandrov int err = 0; 2912594e906SNikolay Aleksandrov 2922594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) { 293907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 2942594e906SNikolay Aleksandrov } else { 2952594e906SNikolay Aleksandrov p = v->port; 296907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 2972594e906SNikolay Aleksandrov masterv = v->brvlan; 2982594e906SNikolay Aleksandrov } 2992594e906SNikolay Aleksandrov 30077751ee8SNikolay Aleksandrov __vlan_delete_pvid(vg, v->vid); 3012594e906SNikolay Aleksandrov if (p) { 3022594e906SNikolay Aleksandrov err = __vlan_vid_del(p->dev, p->br, v->vid); 3032594e906SNikolay Aleksandrov if (err) 3042594e906SNikolay Aleksandrov goto out; 3052594e906SNikolay Aleksandrov } 3062594e906SNikolay Aleksandrov 3076be144f6SNikolay Aleksandrov if (br_vlan_should_use(v)) { 3082594e906SNikolay Aleksandrov v->flags &= ~BRIDGE_VLAN_INFO_BRENTRY; 3096be144f6SNikolay Aleksandrov vg->num_vlans--; 3102594e906SNikolay Aleksandrov } 3112594e906SNikolay Aleksandrov 3122594e906SNikolay Aleksandrov if (masterv != v) { 31377751ee8SNikolay Aleksandrov rhashtable_remove_fast(&vg->vlan_hash, &v->vnode, 31477751ee8SNikolay Aleksandrov br_vlan_rht_params); 3152594e906SNikolay Aleksandrov __vlan_del_list(v); 3162594e906SNikolay Aleksandrov kfree_rcu(v, rcu); 3172594e906SNikolay Aleksandrov } 3182594e906SNikolay Aleksandrov 319f8ed289fSNikolay Aleksandrov br_vlan_put_master(masterv); 3202594e906SNikolay Aleksandrov out: 321bf361ad3SVivien Didelot return err; 3228580e211SToshiaki Makita } 323243a2e63SVlad Yasevich 324f409d0edSNikolay Aleksandrov static void __vlan_group_free(struct net_bridge_vlan_group *vg) 325f409d0edSNikolay Aleksandrov { 326f409d0edSNikolay Aleksandrov WARN_ON(!list_empty(&vg->vlan_list)); 327f409d0edSNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 328f409d0edSNikolay Aleksandrov kfree(vg); 329f409d0edSNikolay Aleksandrov } 330f409d0edSNikolay Aleksandrov 331f409d0edSNikolay Aleksandrov static void __vlan_flush(struct net_bridge_vlan_group *vg) 332243a2e63SVlad Yasevich { 3332594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan, *tmp; 3342594e906SNikolay Aleksandrov 335f409d0edSNikolay Aleksandrov __vlan_delete_pvid(vg, vg->pvid); 336f409d0edSNikolay Aleksandrov list_for_each_entry_safe(vlan, tmp, &vg->vlan_list, vlist) 3372594e906SNikolay Aleksandrov __vlan_del(vlan); 338243a2e63SVlad Yasevich } 339243a2e63SVlad Yasevich 34078851988SVlad Yasevich struct sk_buff *br_handle_vlan(struct net_bridge *br, 3412594e906SNikolay Aleksandrov struct net_bridge_vlan_group *vg, 342a37b85c9SVlad Yasevich struct sk_buff *skb) 343a37b85c9SVlad Yasevich { 3446dada9b1SNikolay Aleksandrov struct br_vlan_stats *stats; 3452594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 346a37b85c9SVlad Yasevich u16 vid; 347a37b85c9SVlad Yasevich 34820adfa1aSVlad Yasevich /* If this packet was not filtered at input, let it pass */ 34920adfa1aSVlad Yasevich if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) 35078851988SVlad Yasevich goto out; 35178851988SVlad Yasevich 3522594e906SNikolay Aleksandrov /* At this point, we know that the frame was filtered and contains 3532594e906SNikolay Aleksandrov * a valid vlan id. If the vlan id has untagged flag set, 3542594e906SNikolay Aleksandrov * send untagged; otherwise, send tagged. 3552594e906SNikolay Aleksandrov */ 3562594e906SNikolay Aleksandrov br_vlan_get_tag(skb, &vid); 3572594e906SNikolay Aleksandrov v = br_vlan_find(vg, vid); 3582594e906SNikolay Aleksandrov /* Vlan entry must be configured at this point. The 359fc92f745SVlad Yasevich * only exception is the bridge is set in promisc mode and the 360fc92f745SVlad Yasevich * packet is destined for the bridge device. In this case 361fc92f745SVlad Yasevich * pass the packet as is. 362fc92f745SVlad Yasevich */ 3632594e906SNikolay Aleksandrov if (!v || !br_vlan_should_use(v)) { 364fc92f745SVlad Yasevich if ((br->dev->flags & IFF_PROMISC) && skb->dev == br->dev) { 365fc92f745SVlad Yasevich goto out; 366fc92f745SVlad Yasevich } else { 367fc92f745SVlad Yasevich kfree_skb(skb); 368fc92f745SVlad Yasevich return NULL; 369fc92f745SVlad Yasevich } 370fc92f745SVlad Yasevich } 3716dada9b1SNikolay Aleksandrov if (br->vlan_stats_enabled) { 3726dada9b1SNikolay Aleksandrov stats = this_cpu_ptr(v->stats); 3736dada9b1SNikolay Aleksandrov u64_stats_update_begin(&stats->syncp); 3746dada9b1SNikolay Aleksandrov stats->tx_bytes += skb->len; 3756dada9b1SNikolay Aleksandrov stats->tx_packets++; 3766dada9b1SNikolay Aleksandrov u64_stats_update_end(&stats->syncp); 3776dada9b1SNikolay Aleksandrov } 3786dada9b1SNikolay Aleksandrov 3792594e906SNikolay Aleksandrov if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED) 38099b192daSToshiaki Makita skb->vlan_tci = 0; 38178851988SVlad Yasevich out: 38278851988SVlad Yasevich return skb; 38378851988SVlad Yasevich } 38478851988SVlad Yasevich 38578851988SVlad Yasevich /* Called under RCU */ 3866dada9b1SNikolay Aleksandrov static bool __allowed_ingress(const struct net_bridge *br, 3876dada9b1SNikolay Aleksandrov struct net_bridge_vlan_group *vg, 38878851988SVlad Yasevich struct sk_buff *skb, u16 *vid) 38978851988SVlad Yasevich { 3906dada9b1SNikolay Aleksandrov struct br_vlan_stats *stats; 3916dada9b1SNikolay Aleksandrov struct net_bridge_vlan *v; 3928580e211SToshiaki Makita bool tagged; 393a37b85c9SVlad Yasevich 39420adfa1aSVlad Yasevich BR_INPUT_SKB_CB(skb)->vlan_filtered = true; 39512464bb8SToshiaki Makita /* If vlan tx offload is disabled on bridge device and frame was 39612464bb8SToshiaki Makita * sent from vlan device on the bridge device, it does not have 39712464bb8SToshiaki Makita * HW accelerated vlan tag. 39812464bb8SToshiaki Makita */ 399df8a39deSJiri Pirko if (unlikely(!skb_vlan_tag_present(skb) && 4006dada9b1SNikolay Aleksandrov skb->protocol == br->vlan_proto)) { 4010d5501c1SVlad Yasevich skb = skb_vlan_untag(skb); 40212464bb8SToshiaki Makita if (unlikely(!skb)) 40312464bb8SToshiaki Makita return false; 40412464bb8SToshiaki Makita } 40512464bb8SToshiaki Makita 4068580e211SToshiaki Makita if (!br_vlan_get_tag(skb, vid)) { 4078580e211SToshiaki Makita /* Tagged frame */ 4086dada9b1SNikolay Aleksandrov if (skb->vlan_proto != br->vlan_proto) { 4098580e211SToshiaki Makita /* Protocol-mismatch, empty out vlan_tci for new tag */ 4108580e211SToshiaki Makita skb_push(skb, ETH_HLEN); 41162749e2cSJiri Pirko skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto, 412df8a39deSJiri Pirko skb_vlan_tag_get(skb)); 4138580e211SToshiaki Makita if (unlikely(!skb)) 4148580e211SToshiaki Makita return false; 4158580e211SToshiaki Makita 4168580e211SToshiaki Makita skb_pull(skb, ETH_HLEN); 4178580e211SToshiaki Makita skb_reset_mac_len(skb); 4188580e211SToshiaki Makita *vid = 0; 4198580e211SToshiaki Makita tagged = false; 4208580e211SToshiaki Makita } else { 4218580e211SToshiaki Makita tagged = true; 4228580e211SToshiaki Makita } 4238580e211SToshiaki Makita } else { 4248580e211SToshiaki Makita /* Untagged frame */ 4258580e211SToshiaki Makita tagged = false; 4268580e211SToshiaki Makita } 4278580e211SToshiaki Makita 428b90356ceSToshiaki Makita if (!*vid) { 42977751ee8SNikolay Aleksandrov u16 pvid = br_get_pvid(vg); 43077751ee8SNikolay Aleksandrov 431b90356ceSToshiaki Makita /* Frame had a tag with VID 0 or did not have a tag. 432b90356ceSToshiaki Makita * See if pvid is set on this port. That tells us which 433b90356ceSToshiaki Makita * vlan untagged or priority-tagged traffic belongs to. 43478851988SVlad Yasevich */ 4353df6bf45SVlad Yasevich if (!pvid) 436eb707618SToshiaki Makita goto drop; 43778851988SVlad Yasevich 438b90356ceSToshiaki Makita /* PVID is set on this port. Any untagged or priority-tagged 439b90356ceSToshiaki Makita * ingress frame is considered to belong to this vlan. 44078851988SVlad Yasevich */ 441dfb5fa32SToshiaki Makita *vid = pvid; 4428580e211SToshiaki Makita if (likely(!tagged)) 443b90356ceSToshiaki Makita /* Untagged Frame. */ 4446dada9b1SNikolay Aleksandrov __vlan_hwaccel_put_tag(skb, br->vlan_proto, pvid); 445b90356ceSToshiaki Makita else 446b90356ceSToshiaki Makita /* Priority-tagged Frame. 447b90356ceSToshiaki Makita * At this point, We know that skb->vlan_tci had 448b90356ceSToshiaki Makita * VLAN_TAG_PRESENT bit and its VID field was 0x000. 449b90356ceSToshiaki Makita * We update only VID field and preserve PCP field. 450b90356ceSToshiaki Makita */ 451b90356ceSToshiaki Makita skb->vlan_tci |= pvid; 452b90356ceSToshiaki Makita 4536dada9b1SNikolay Aleksandrov /* if stats are disabled we can avoid the lookup */ 4546dada9b1SNikolay Aleksandrov if (!br->vlan_stats_enabled) 45578851988SVlad Yasevich return true; 45678851988SVlad Yasevich } 45777751ee8SNikolay Aleksandrov v = br_vlan_find(vg, *vid); 4586dada9b1SNikolay Aleksandrov if (!v || !br_vlan_should_use(v)) 4596dada9b1SNikolay Aleksandrov goto drop; 4606dada9b1SNikolay Aleksandrov 4616dada9b1SNikolay Aleksandrov if (br->vlan_stats_enabled) { 4626dada9b1SNikolay Aleksandrov stats = this_cpu_ptr(v->stats); 4636dada9b1SNikolay Aleksandrov u64_stats_update_begin(&stats->syncp); 4646dada9b1SNikolay Aleksandrov stats->rx_bytes += skb->len; 4656dada9b1SNikolay Aleksandrov stats->rx_packets++; 4666dada9b1SNikolay Aleksandrov u64_stats_update_end(&stats->syncp); 4676dada9b1SNikolay Aleksandrov } 4686dada9b1SNikolay Aleksandrov 469a37b85c9SVlad Yasevich return true; 4706dada9b1SNikolay Aleksandrov 471eb707618SToshiaki Makita drop: 472eb707618SToshiaki Makita kfree_skb(skb); 473a37b85c9SVlad Yasevich return false; 474a37b85c9SVlad Yasevich } 475a37b85c9SVlad Yasevich 47677751ee8SNikolay Aleksandrov bool br_allowed_ingress(const struct net_bridge *br, 47777751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg, struct sk_buff *skb, 4782594e906SNikolay Aleksandrov u16 *vid) 4792594e906SNikolay Aleksandrov { 4802594e906SNikolay Aleksandrov /* If VLAN filtering is disabled on the bridge, all packets are 4812594e906SNikolay Aleksandrov * permitted. 4822594e906SNikolay Aleksandrov */ 4832594e906SNikolay Aleksandrov if (!br->vlan_enabled) { 4842594e906SNikolay Aleksandrov BR_INPUT_SKB_CB(skb)->vlan_filtered = false; 4852594e906SNikolay Aleksandrov return true; 4862594e906SNikolay Aleksandrov } 4872594e906SNikolay Aleksandrov 4886dada9b1SNikolay Aleksandrov return __allowed_ingress(br, vg, skb, vid); 4892594e906SNikolay Aleksandrov } 4902594e906SNikolay Aleksandrov 49185f46c6bSVlad Yasevich /* Called under RCU. */ 4922594e906SNikolay Aleksandrov bool br_allowed_egress(struct net_bridge_vlan_group *vg, 49385f46c6bSVlad Yasevich const struct sk_buff *skb) 49485f46c6bSVlad Yasevich { 4952594e906SNikolay Aleksandrov const struct net_bridge_vlan *v; 49685f46c6bSVlad Yasevich u16 vid; 49785f46c6bSVlad Yasevich 49820adfa1aSVlad Yasevich /* If this packet was not filtered at input, let it pass */ 49920adfa1aSVlad Yasevich if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) 50085f46c6bSVlad Yasevich return true; 50185f46c6bSVlad Yasevich 50285f46c6bSVlad Yasevich br_vlan_get_tag(skb, &vid); 5032594e906SNikolay Aleksandrov v = br_vlan_find(vg, vid); 5042594e906SNikolay Aleksandrov if (v && br_vlan_should_use(v)) 50585f46c6bSVlad Yasevich return true; 50685f46c6bSVlad Yasevich 50785f46c6bSVlad Yasevich return false; 50885f46c6bSVlad Yasevich } 50985f46c6bSVlad Yasevich 510e0d7968aSToshiaki Makita /* Called under RCU */ 511e0d7968aSToshiaki Makita bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) 512e0d7968aSToshiaki Makita { 513468e7944SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 514e0d7968aSToshiaki Makita struct net_bridge *br = p->br; 515e0d7968aSToshiaki Makita 51620adfa1aSVlad Yasevich /* If filtering was disabled at input, let it pass. */ 517c095f248SVlad Yasevich if (!br->vlan_enabled) 518e0d7968aSToshiaki Makita return true; 519e0d7968aSToshiaki Makita 520eca1e006SIdo Schimmel vg = nbp_vlan_group_rcu(p); 521468e7944SNikolay Aleksandrov if (!vg || !vg->num_vlans) 522e0d7968aSToshiaki Makita return false; 523e0d7968aSToshiaki Makita 5248580e211SToshiaki Makita if (!br_vlan_get_tag(skb, vid) && skb->vlan_proto != br->vlan_proto) 5258580e211SToshiaki Makita *vid = 0; 5268580e211SToshiaki Makita 527e0d7968aSToshiaki Makita if (!*vid) { 52877751ee8SNikolay Aleksandrov *vid = br_get_pvid(vg); 5293df6bf45SVlad Yasevich if (!*vid) 530e0d7968aSToshiaki Makita return false; 531e0d7968aSToshiaki Makita 532e0d7968aSToshiaki Makita return true; 533e0d7968aSToshiaki Makita } 534e0d7968aSToshiaki Makita 53577751ee8SNikolay Aleksandrov if (br_vlan_find(vg, *vid)) 536e0d7968aSToshiaki Makita return true; 537e0d7968aSToshiaki Makita 538e0d7968aSToshiaki Makita return false; 539e0d7968aSToshiaki Makita } 540e0d7968aSToshiaki Makita 5418adff41cSToshiaki Makita /* Must be protected by RTNL. 5428adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 5438adff41cSToshiaki Makita */ 544552406c4SVlad Yasevich int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags) 545243a2e63SVlad Yasevich { 546907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 5472594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 5482594e906SNikolay Aleksandrov int ret; 549243a2e63SVlad Yasevich 550243a2e63SVlad Yasevich ASSERT_RTNL(); 551243a2e63SVlad Yasevich 552907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 553907b1e6eSNikolay Aleksandrov vlan = br_vlan_find(vg, vid); 5542594e906SNikolay Aleksandrov if (vlan) { 5552594e906SNikolay Aleksandrov if (!br_vlan_is_brentry(vlan)) { 5562594e906SNikolay Aleksandrov /* Trying to change flags of non-existent bridge vlan */ 5572594e906SNikolay Aleksandrov if (!(flags & BRIDGE_VLAN_INFO_BRENTRY)) 5582594e906SNikolay Aleksandrov return -EINVAL; 5592594e906SNikolay Aleksandrov /* It was only kept for port vlans, now make it real */ 5602594e906SNikolay Aleksandrov ret = br_fdb_insert(br, NULL, br->dev->dev_addr, 5612594e906SNikolay Aleksandrov vlan->vid); 5622594e906SNikolay Aleksandrov if (ret) { 5632594e906SNikolay Aleksandrov br_err(br, "failed insert local address into bridge forwarding table\n"); 5642594e906SNikolay Aleksandrov return ret; 5652594e906SNikolay Aleksandrov } 5662594e906SNikolay Aleksandrov atomic_inc(&vlan->refcnt); 5672594e906SNikolay Aleksandrov vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY; 568907b1e6eSNikolay Aleksandrov vg->num_vlans++; 5692594e906SNikolay Aleksandrov } 5702594e906SNikolay Aleksandrov __vlan_add_flags(vlan, flags); 5712594e906SNikolay Aleksandrov return 0; 5722594e906SNikolay Aleksandrov } 573243a2e63SVlad Yasevich 5742594e906SNikolay Aleksandrov vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); 5752594e906SNikolay Aleksandrov if (!vlan) 576243a2e63SVlad Yasevich return -ENOMEM; 577243a2e63SVlad Yasevich 5786dada9b1SNikolay Aleksandrov vlan->stats = netdev_alloc_pcpu_stats(struct br_vlan_stats); 5796dada9b1SNikolay Aleksandrov if (!vlan->stats) { 5806dada9b1SNikolay Aleksandrov kfree(vlan); 5816dada9b1SNikolay Aleksandrov return -ENOMEM; 5826dada9b1SNikolay Aleksandrov } 5832594e906SNikolay Aleksandrov vlan->vid = vid; 5842594e906SNikolay Aleksandrov vlan->flags = flags | BRIDGE_VLAN_INFO_MASTER; 5852594e906SNikolay Aleksandrov vlan->flags &= ~BRIDGE_VLAN_INFO_PVID; 5862594e906SNikolay Aleksandrov vlan->br = br; 5872594e906SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_BRENTRY) 5882594e906SNikolay Aleksandrov atomic_set(&vlan->refcnt, 1); 5892594e906SNikolay Aleksandrov ret = __vlan_add(vlan, flags); 5906dada9b1SNikolay Aleksandrov if (ret) { 5916dada9b1SNikolay Aleksandrov free_percpu(vlan->stats); 5922594e906SNikolay Aleksandrov kfree(vlan); 5936dada9b1SNikolay Aleksandrov } 594243a2e63SVlad Yasevich 5952594e906SNikolay Aleksandrov return ret; 596243a2e63SVlad Yasevich } 597243a2e63SVlad Yasevich 5988adff41cSToshiaki Makita /* Must be protected by RTNL. 5998adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 6008adff41cSToshiaki Makita */ 601243a2e63SVlad Yasevich int br_vlan_delete(struct net_bridge *br, u16 vid) 602243a2e63SVlad Yasevich { 603907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 6042594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 605243a2e63SVlad Yasevich 606243a2e63SVlad Yasevich ASSERT_RTNL(); 607243a2e63SVlad Yasevich 608907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 609907b1e6eSNikolay Aleksandrov v = br_vlan_find(vg, vid); 6102594e906SNikolay Aleksandrov if (!v || !br_vlan_is_brentry(v)) 6112594e906SNikolay Aleksandrov return -ENOENT; 612243a2e63SVlad Yasevich 613424bb9c9SToshiaki Makita br_fdb_find_delete_local(br, NULL, br->dev->dev_addr, vid); 6143741873bSRoopa Prabhu br_fdb_delete_by_port(br, NULL, vid, 0); 615bc9a25d2SVlad Yasevich 6162594e906SNikolay Aleksandrov return __vlan_del(v); 617243a2e63SVlad Yasevich } 618243a2e63SVlad Yasevich 619243a2e63SVlad Yasevich void br_vlan_flush(struct net_bridge *br) 620243a2e63SVlad Yasevich { 621f409d0edSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 622f409d0edSNikolay Aleksandrov 623243a2e63SVlad Yasevich ASSERT_RTNL(); 624243a2e63SVlad Yasevich 625f409d0edSNikolay Aleksandrov vg = br_vlan_group(br); 626f409d0edSNikolay Aleksandrov __vlan_flush(vg); 627f409d0edSNikolay Aleksandrov RCU_INIT_POINTER(br->vlgrp, NULL); 628f409d0edSNikolay Aleksandrov synchronize_rcu(); 629f409d0edSNikolay Aleksandrov __vlan_group_free(vg); 630243a2e63SVlad Yasevich } 631243a2e63SVlad Yasevich 6322594e906SNikolay Aleksandrov struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid) 6332b292fb4SToshiaki Makita { 6342594e906SNikolay Aleksandrov if (!vg) 6352594e906SNikolay Aleksandrov return NULL; 6362b292fb4SToshiaki Makita 6372594e906SNikolay Aleksandrov return br_vlan_lookup(&vg->vlan_hash, vid); 6382b292fb4SToshiaki Makita } 6392b292fb4SToshiaki Makita 640204177f3SToshiaki Makita /* Must be protected by RTNL. */ 641204177f3SToshiaki Makita static void recalculate_group_addr(struct net_bridge *br) 642204177f3SToshiaki Makita { 643204177f3SToshiaki Makita if (br->group_addr_set) 644204177f3SToshiaki Makita return; 645204177f3SToshiaki Makita 646204177f3SToshiaki Makita spin_lock_bh(&br->lock); 647204177f3SToshiaki Makita if (!br->vlan_enabled || br->vlan_proto == htons(ETH_P_8021Q)) { 648204177f3SToshiaki Makita /* Bridge Group Address */ 649204177f3SToshiaki Makita br->group_addr[5] = 0x00; 650204177f3SToshiaki Makita } else { /* vlan_enabled && ETH_P_8021AD */ 651204177f3SToshiaki Makita /* Provider Bridge Group Address */ 652204177f3SToshiaki Makita br->group_addr[5] = 0x08; 653204177f3SToshiaki Makita } 654204177f3SToshiaki Makita spin_unlock_bh(&br->lock); 655204177f3SToshiaki Makita } 656204177f3SToshiaki Makita 657204177f3SToshiaki Makita /* Must be protected by RTNL. */ 658204177f3SToshiaki Makita void br_recalculate_fwd_mask(struct net_bridge *br) 659204177f3SToshiaki Makita { 660204177f3SToshiaki Makita if (!br->vlan_enabled || br->vlan_proto == htons(ETH_P_8021Q)) 661204177f3SToshiaki Makita br->group_fwd_mask_required = BR_GROUPFWD_DEFAULT; 662204177f3SToshiaki Makita else /* vlan_enabled && ETH_P_8021AD */ 663204177f3SToshiaki Makita br->group_fwd_mask_required = BR_GROUPFWD_8021AD & 664204177f3SToshiaki Makita ~(1u << br->group_addr[5]); 665204177f3SToshiaki Makita } 666204177f3SToshiaki Makita 667a7854037SNikolay Aleksandrov int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 668243a2e63SVlad Yasevich { 6696b72a770SElad Raz struct switchdev_attr attr = { 6706b72a770SElad Raz .orig_dev = br->dev, 6716b72a770SElad Raz .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, 6726b72a770SElad Raz .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, 6736b72a770SElad Raz .u.vlan_filtering = val, 6746b72a770SElad Raz }; 6756b72a770SElad Raz int err; 6766b72a770SElad Raz 677243a2e63SVlad Yasevich if (br->vlan_enabled == val) 678a7854037SNikolay Aleksandrov return 0; 679243a2e63SVlad Yasevich 6806b72a770SElad Raz err = switchdev_port_attr_set(br->dev, &attr); 6816b72a770SElad Raz if (err && err != -EOPNOTSUPP) 6826b72a770SElad Raz return err; 6836b72a770SElad Raz 684243a2e63SVlad Yasevich br->vlan_enabled = val; 6852796d0c6SVlad Yasevich br_manage_promisc(br); 686204177f3SToshiaki Makita recalculate_group_addr(br); 687204177f3SToshiaki Makita br_recalculate_fwd_mask(br); 688243a2e63SVlad Yasevich 689a7854037SNikolay Aleksandrov return 0; 690a7854037SNikolay Aleksandrov } 691a7854037SNikolay Aleksandrov 692a7854037SNikolay Aleksandrov int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 693a7854037SNikolay Aleksandrov { 694047831a9SXin Long return __br_vlan_filter_toggle(br, val); 695243a2e63SVlad Yasevich } 696243a2e63SVlad Yasevich 697d2d427b3SToshiaki Makita int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) 698204177f3SToshiaki Makita { 699204177f3SToshiaki Makita int err = 0; 700204177f3SToshiaki Makita struct net_bridge_port *p; 7012594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 702907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 703d2d427b3SToshiaki Makita __be16 oldproto; 704204177f3SToshiaki Makita 705204177f3SToshiaki Makita if (br->vlan_proto == proto) 706d2d427b3SToshiaki Makita return 0; 707204177f3SToshiaki Makita 708204177f3SToshiaki Makita /* Add VLANs for the new proto to the device filter. */ 709204177f3SToshiaki Makita list_for_each_entry(p, &br->port_list, list) { 710907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 711907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) { 7122594e906SNikolay Aleksandrov err = vlan_vid_add(p->dev, proto, vlan->vid); 713204177f3SToshiaki Makita if (err) 714204177f3SToshiaki Makita goto err_filt; 715204177f3SToshiaki Makita } 716204177f3SToshiaki Makita } 717204177f3SToshiaki Makita 718204177f3SToshiaki Makita oldproto = br->vlan_proto; 719204177f3SToshiaki Makita br->vlan_proto = proto; 720204177f3SToshiaki Makita 721204177f3SToshiaki Makita recalculate_group_addr(br); 722204177f3SToshiaki Makita br_recalculate_fwd_mask(br); 723204177f3SToshiaki Makita 724204177f3SToshiaki Makita /* Delete VLANs for the old proto from the device filter. */ 725907b1e6eSNikolay Aleksandrov list_for_each_entry(p, &br->port_list, list) { 726907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 727907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) 7282594e906SNikolay Aleksandrov vlan_vid_del(p->dev, oldproto, vlan->vid); 729907b1e6eSNikolay Aleksandrov } 730204177f3SToshiaki Makita 731d2d427b3SToshiaki Makita return 0; 732204177f3SToshiaki Makita 733204177f3SToshiaki Makita err_filt: 734907b1e6eSNikolay Aleksandrov list_for_each_entry_continue_reverse(vlan, &vg->vlan_list, vlist) 7352594e906SNikolay Aleksandrov vlan_vid_del(p->dev, proto, vlan->vid); 736204177f3SToshiaki Makita 737907b1e6eSNikolay Aleksandrov list_for_each_entry_continue_reverse(p, &br->port_list, list) { 738907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 739907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) 7402594e906SNikolay Aleksandrov vlan_vid_del(p->dev, proto, vlan->vid); 741907b1e6eSNikolay Aleksandrov } 742204177f3SToshiaki Makita 743d2d427b3SToshiaki Makita return err; 744d2d427b3SToshiaki Makita } 745d2d427b3SToshiaki Makita 746d2d427b3SToshiaki Makita int br_vlan_set_proto(struct net_bridge *br, unsigned long val) 747d2d427b3SToshiaki Makita { 748d2d427b3SToshiaki Makita if (val != ETH_P_8021Q && val != ETH_P_8021AD) 749d2d427b3SToshiaki Makita return -EPROTONOSUPPORT; 750d2d427b3SToshiaki Makita 751047831a9SXin Long return __br_vlan_set_proto(br, htons(val)); 752204177f3SToshiaki Makita } 753204177f3SToshiaki Makita 7546dada9b1SNikolay Aleksandrov int br_vlan_set_stats(struct net_bridge *br, unsigned long val) 7556dada9b1SNikolay Aleksandrov { 7566dada9b1SNikolay Aleksandrov switch (val) { 7576dada9b1SNikolay Aleksandrov case 0: 7586dada9b1SNikolay Aleksandrov case 1: 7596dada9b1SNikolay Aleksandrov br->vlan_stats_enabled = val; 7606dada9b1SNikolay Aleksandrov break; 7616dada9b1SNikolay Aleksandrov default: 7626dada9b1SNikolay Aleksandrov return -EINVAL; 7636dada9b1SNikolay Aleksandrov } 7646dada9b1SNikolay Aleksandrov 7656dada9b1SNikolay Aleksandrov return 0; 7666dada9b1SNikolay Aleksandrov } 7676dada9b1SNikolay Aleksandrov 76877751ee8SNikolay Aleksandrov static bool vlan_default_pvid(struct net_bridge_vlan_group *vg, u16 vid) 7695be5a2dfSVlad Yasevich { 7702594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 7712594e906SNikolay Aleksandrov 77277751ee8SNikolay Aleksandrov if (vid != vg->pvid) 7732594e906SNikolay Aleksandrov return false; 7742594e906SNikolay Aleksandrov 7752594e906SNikolay Aleksandrov v = br_vlan_lookup(&vg->vlan_hash, vid); 7762594e906SNikolay Aleksandrov if (v && br_vlan_should_use(v) && 7772594e906SNikolay Aleksandrov (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)) 7782594e906SNikolay Aleksandrov return true; 7792594e906SNikolay Aleksandrov 7802594e906SNikolay Aleksandrov return false; 7815be5a2dfSVlad Yasevich } 7825be5a2dfSVlad Yasevich 7835be5a2dfSVlad Yasevich static void br_vlan_disable_default_pvid(struct net_bridge *br) 7845be5a2dfSVlad Yasevich { 7855be5a2dfSVlad Yasevich struct net_bridge_port *p; 7865be5a2dfSVlad Yasevich u16 pvid = br->default_pvid; 7875be5a2dfSVlad Yasevich 7885be5a2dfSVlad Yasevich /* Disable default_pvid on all ports where it is still 7895be5a2dfSVlad Yasevich * configured. 7905be5a2dfSVlad Yasevich */ 791907b1e6eSNikolay Aleksandrov if (vlan_default_pvid(br_vlan_group(br), pvid)) 7925be5a2dfSVlad Yasevich br_vlan_delete(br, pvid); 7935be5a2dfSVlad Yasevich 7945be5a2dfSVlad Yasevich list_for_each_entry(p, &br->port_list, list) { 795907b1e6eSNikolay Aleksandrov if (vlan_default_pvid(nbp_vlan_group(p), pvid)) 7965be5a2dfSVlad Yasevich nbp_vlan_delete(p, pvid); 7975be5a2dfSVlad Yasevich } 7985be5a2dfSVlad Yasevich 7995be5a2dfSVlad Yasevich br->default_pvid = 0; 8005be5a2dfSVlad Yasevich } 8015be5a2dfSVlad Yasevich 8020f963b75SNikolay Aleksandrov int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid) 8035be5a2dfSVlad Yasevich { 8042594e906SNikolay Aleksandrov const struct net_bridge_vlan *pvent; 805907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 8065be5a2dfSVlad Yasevich struct net_bridge_port *p; 8075be5a2dfSVlad Yasevich u16 old_pvid; 8085be5a2dfSVlad Yasevich int err = 0; 8095be5a2dfSVlad Yasevich unsigned long *changed; 8105be5a2dfSVlad Yasevich 8110f963b75SNikolay Aleksandrov if (!pvid) { 8120f963b75SNikolay Aleksandrov br_vlan_disable_default_pvid(br); 8130f963b75SNikolay Aleksandrov return 0; 8140f963b75SNikolay Aleksandrov } 8150f963b75SNikolay Aleksandrov 8165be5a2dfSVlad Yasevich changed = kcalloc(BITS_TO_LONGS(BR_MAX_PORTS), sizeof(unsigned long), 8175be5a2dfSVlad Yasevich GFP_KERNEL); 8185be5a2dfSVlad Yasevich if (!changed) 8195be5a2dfSVlad Yasevich return -ENOMEM; 8205be5a2dfSVlad Yasevich 8215be5a2dfSVlad Yasevich old_pvid = br->default_pvid; 8225be5a2dfSVlad Yasevich 8235be5a2dfSVlad Yasevich /* Update default_pvid config only if we do not conflict with 8245be5a2dfSVlad Yasevich * user configuration. 8255be5a2dfSVlad Yasevich */ 826907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 827907b1e6eSNikolay Aleksandrov pvent = br_vlan_find(vg, pvid); 828907b1e6eSNikolay Aleksandrov if ((!old_pvid || vlan_default_pvid(vg, old_pvid)) && 8292594e906SNikolay Aleksandrov (!pvent || !br_vlan_should_use(pvent))) { 8305be5a2dfSVlad Yasevich err = br_vlan_add(br, pvid, 8315be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 8322594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 8332594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY); 8345be5a2dfSVlad Yasevich if (err) 8355be5a2dfSVlad Yasevich goto out; 8365be5a2dfSVlad Yasevich br_vlan_delete(br, old_pvid); 8375be5a2dfSVlad Yasevich set_bit(0, changed); 8385be5a2dfSVlad Yasevich } 8395be5a2dfSVlad Yasevich 8405be5a2dfSVlad Yasevich list_for_each_entry(p, &br->port_list, list) { 8415be5a2dfSVlad Yasevich /* Update default_pvid config only if we do not conflict with 8425be5a2dfSVlad Yasevich * user configuration. 8435be5a2dfSVlad Yasevich */ 844907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 8455be5a2dfSVlad Yasevich if ((old_pvid && 846907b1e6eSNikolay Aleksandrov !vlan_default_pvid(vg, old_pvid)) || 847907b1e6eSNikolay Aleksandrov br_vlan_find(vg, pvid)) 8485be5a2dfSVlad Yasevich continue; 8495be5a2dfSVlad Yasevich 8505be5a2dfSVlad Yasevich err = nbp_vlan_add(p, pvid, 8515be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 8525be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_UNTAGGED); 8535be5a2dfSVlad Yasevich if (err) 8545be5a2dfSVlad Yasevich goto err_port; 8555be5a2dfSVlad Yasevich nbp_vlan_delete(p, old_pvid); 8565be5a2dfSVlad Yasevich set_bit(p->port_no, changed); 8575be5a2dfSVlad Yasevich } 8585be5a2dfSVlad Yasevich 8595be5a2dfSVlad Yasevich br->default_pvid = pvid; 8605be5a2dfSVlad Yasevich 8615be5a2dfSVlad Yasevich out: 8625be5a2dfSVlad Yasevich kfree(changed); 8635be5a2dfSVlad Yasevich return err; 8645be5a2dfSVlad Yasevich 8655be5a2dfSVlad Yasevich err_port: 8665be5a2dfSVlad Yasevich list_for_each_entry_continue_reverse(p, &br->port_list, list) { 8675be5a2dfSVlad Yasevich if (!test_bit(p->port_no, changed)) 8685be5a2dfSVlad Yasevich continue; 8695be5a2dfSVlad Yasevich 8705be5a2dfSVlad Yasevich if (old_pvid) 8715be5a2dfSVlad Yasevich nbp_vlan_add(p, old_pvid, 8725be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 8735be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_UNTAGGED); 8745be5a2dfSVlad Yasevich nbp_vlan_delete(p, pvid); 8755be5a2dfSVlad Yasevich } 8765be5a2dfSVlad Yasevich 8775be5a2dfSVlad Yasevich if (test_bit(0, changed)) { 8785be5a2dfSVlad Yasevich if (old_pvid) 8795be5a2dfSVlad Yasevich br_vlan_add(br, old_pvid, 8805be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 8812594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 8822594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY); 8835be5a2dfSVlad Yasevich br_vlan_delete(br, pvid); 8845be5a2dfSVlad Yasevich } 8855be5a2dfSVlad Yasevich goto out; 8865be5a2dfSVlad Yasevich } 8875be5a2dfSVlad Yasevich 88896a20d9dSVlad Yasevich int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val) 88996a20d9dSVlad Yasevich { 89096a20d9dSVlad Yasevich u16 pvid = val; 89196a20d9dSVlad Yasevich int err = 0; 89296a20d9dSVlad Yasevich 8935be5a2dfSVlad Yasevich if (val >= VLAN_VID_MASK) 89496a20d9dSVlad Yasevich return -EINVAL; 89596a20d9dSVlad Yasevich 89696a20d9dSVlad Yasevich if (pvid == br->default_pvid) 897047831a9SXin Long goto out; 89896a20d9dSVlad Yasevich 89996a20d9dSVlad Yasevich /* Only allow default pvid change when filtering is disabled */ 90096a20d9dSVlad Yasevich if (br->vlan_enabled) { 90196a20d9dSVlad Yasevich pr_info_once("Please disable vlan filtering to change default_pvid\n"); 90296a20d9dSVlad Yasevich err = -EPERM; 903047831a9SXin Long goto out; 90496a20d9dSVlad Yasevich } 9055be5a2dfSVlad Yasevich err = __br_vlan_set_default_pvid(br, pvid); 906047831a9SXin Long out: 90796a20d9dSVlad Yasevich return err; 90896a20d9dSVlad Yasevich } 90996a20d9dSVlad Yasevich 9105be5a2dfSVlad Yasevich int br_vlan_init(struct net_bridge *br) 9118580e211SToshiaki Makita { 912907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 9132594e906SNikolay Aleksandrov int ret = -ENOMEM; 9142594e906SNikolay Aleksandrov 915907b1e6eSNikolay Aleksandrov vg = kzalloc(sizeof(*vg), GFP_KERNEL); 916907b1e6eSNikolay Aleksandrov if (!vg) 9172594e906SNikolay Aleksandrov goto out; 918907b1e6eSNikolay Aleksandrov ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); 9192594e906SNikolay Aleksandrov if (ret) 9202594e906SNikolay Aleksandrov goto err_rhtbl; 921907b1e6eSNikolay Aleksandrov INIT_LIST_HEAD(&vg->vlan_list); 9228580e211SToshiaki Makita br->vlan_proto = htons(ETH_P_8021Q); 92396a20d9dSVlad Yasevich br->default_pvid = 1; 924907b1e6eSNikolay Aleksandrov rcu_assign_pointer(br->vlgrp, vg); 9252594e906SNikolay Aleksandrov ret = br_vlan_add(br, 1, 9262594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED | 9272594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY); 9282594e906SNikolay Aleksandrov if (ret) 9292594e906SNikolay Aleksandrov goto err_vlan_add; 9302594e906SNikolay Aleksandrov 9312594e906SNikolay Aleksandrov out: 9322594e906SNikolay Aleksandrov return ret; 9332594e906SNikolay Aleksandrov 9342594e906SNikolay Aleksandrov err_vlan_add: 935907b1e6eSNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 9362594e906SNikolay Aleksandrov err_rhtbl: 937907b1e6eSNikolay Aleksandrov kfree(vg); 9382594e906SNikolay Aleksandrov 9392594e906SNikolay Aleksandrov goto out; 9402594e906SNikolay Aleksandrov } 9412594e906SNikolay Aleksandrov 9422594e906SNikolay Aleksandrov int nbp_vlan_init(struct net_bridge_port *p) 9432594e906SNikolay Aleksandrov { 944404cdbf0SElad Raz struct switchdev_attr attr = { 945404cdbf0SElad Raz .orig_dev = p->br->dev, 946404cdbf0SElad Raz .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, 947404cdbf0SElad Raz .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, 948404cdbf0SElad Raz .u.vlan_filtering = p->br->vlan_enabled, 949404cdbf0SElad Raz }; 950263344e6SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 9512594e906SNikolay Aleksandrov int ret = -ENOMEM; 9522594e906SNikolay Aleksandrov 953263344e6SNikolay Aleksandrov vg = kzalloc(sizeof(struct net_bridge_vlan_group), GFP_KERNEL); 954263344e6SNikolay Aleksandrov if (!vg) 9552594e906SNikolay Aleksandrov goto out; 9562594e906SNikolay Aleksandrov 957404cdbf0SElad Raz ret = switchdev_port_attr_set(p->dev, &attr); 958404cdbf0SElad Raz if (ret && ret != -EOPNOTSUPP) 959404cdbf0SElad Raz goto err_vlan_enabled; 960404cdbf0SElad Raz 961263344e6SNikolay Aleksandrov ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); 9622594e906SNikolay Aleksandrov if (ret) 9632594e906SNikolay Aleksandrov goto err_rhtbl; 964263344e6SNikolay Aleksandrov INIT_LIST_HEAD(&vg->vlan_list); 965907b1e6eSNikolay Aleksandrov rcu_assign_pointer(p->vlgrp, vg); 9662594e906SNikolay Aleksandrov if (p->br->default_pvid) { 9672594e906SNikolay Aleksandrov ret = nbp_vlan_add(p, p->br->default_pvid, 9682594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_PVID | 9692594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED); 9702594e906SNikolay Aleksandrov if (ret) 9712594e906SNikolay Aleksandrov goto err_vlan_add; 9722594e906SNikolay Aleksandrov } 9732594e906SNikolay Aleksandrov out: 9742594e906SNikolay Aleksandrov return ret; 9752594e906SNikolay Aleksandrov 9762594e906SNikolay Aleksandrov err_vlan_add: 97707bc588fSIdo Schimmel RCU_INIT_POINTER(p->vlgrp, NULL); 97807bc588fSIdo Schimmel synchronize_rcu(); 979263344e6SNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 980404cdbf0SElad Raz err_vlan_enabled: 9812594e906SNikolay Aleksandrov err_rhtbl: 982263344e6SNikolay Aleksandrov kfree(vg); 9832594e906SNikolay Aleksandrov 9842594e906SNikolay Aleksandrov goto out; 9858580e211SToshiaki Makita } 9868580e211SToshiaki Makita 9878adff41cSToshiaki Makita /* Must be protected by RTNL. 9888adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 9898adff41cSToshiaki Makita */ 990552406c4SVlad Yasevich int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) 991243a2e63SVlad Yasevich { 9927fbac984SIdo Schimmel struct switchdev_obj_port_vlan v = { 9937fbac984SIdo Schimmel .obj.orig_dev = port->dev, 9947fbac984SIdo Schimmel .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, 9957fbac984SIdo Schimmel .flags = flags, 9967fbac984SIdo Schimmel .vid_begin = vid, 9977fbac984SIdo Schimmel .vid_end = vid, 9987fbac984SIdo Schimmel }; 9992594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 10002594e906SNikolay Aleksandrov int ret; 1001243a2e63SVlad Yasevich 1002243a2e63SVlad Yasevich ASSERT_RTNL(); 1003243a2e63SVlad Yasevich 1004907b1e6eSNikolay Aleksandrov vlan = br_vlan_find(nbp_vlan_group(port), vid); 10052594e906SNikolay Aleksandrov if (vlan) { 10067fbac984SIdo Schimmel /* Pass the flags to the hardware bridge */ 10077fbac984SIdo Schimmel ret = switchdev_port_obj_add(port->dev, &v.obj); 10087fbac984SIdo Schimmel if (ret && ret != -EOPNOTSUPP) 10097fbac984SIdo Schimmel return ret; 10102594e906SNikolay Aleksandrov __vlan_add_flags(vlan, flags); 10112594e906SNikolay Aleksandrov return 0; 1012243a2e63SVlad Yasevich } 1013243a2e63SVlad Yasevich 10142594e906SNikolay Aleksandrov vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); 10152594e906SNikolay Aleksandrov if (!vlan) 10162594e906SNikolay Aleksandrov return -ENOMEM; 1017243a2e63SVlad Yasevich 10182594e906SNikolay Aleksandrov vlan->vid = vid; 10192594e906SNikolay Aleksandrov vlan->port = port; 10202594e906SNikolay Aleksandrov ret = __vlan_add(vlan, flags); 10212594e906SNikolay Aleksandrov if (ret) 10222594e906SNikolay Aleksandrov kfree(vlan); 1023243a2e63SVlad Yasevich 10242594e906SNikolay Aleksandrov return ret; 1025243a2e63SVlad Yasevich } 1026243a2e63SVlad Yasevich 10278adff41cSToshiaki Makita /* Must be protected by RTNL. 10288adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 10298adff41cSToshiaki Makita */ 1030243a2e63SVlad Yasevich int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) 1031243a2e63SVlad Yasevich { 10322594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 1033243a2e63SVlad Yasevich 1034243a2e63SVlad Yasevich ASSERT_RTNL(); 1035243a2e63SVlad Yasevich 1036907b1e6eSNikolay Aleksandrov v = br_vlan_find(nbp_vlan_group(port), vid); 10372594e906SNikolay Aleksandrov if (!v) 10382594e906SNikolay Aleksandrov return -ENOENT; 1039424bb9c9SToshiaki Makita br_fdb_find_delete_local(port->br, port, port->dev->dev_addr, vid); 10401ea2d020SNikolay Aleksandrov br_fdb_delete_by_port(port->br, port, vid, 0); 1041bc9a25d2SVlad Yasevich 10422594e906SNikolay Aleksandrov return __vlan_del(v); 1043243a2e63SVlad Yasevich } 1044243a2e63SVlad Yasevich 1045243a2e63SVlad Yasevich void nbp_vlan_flush(struct net_bridge_port *port) 1046243a2e63SVlad Yasevich { 1047f409d0edSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 1048f409d0edSNikolay Aleksandrov 1049243a2e63SVlad Yasevich ASSERT_RTNL(); 1050243a2e63SVlad Yasevich 1051f409d0edSNikolay Aleksandrov vg = nbp_vlan_group(port); 1052f409d0edSNikolay Aleksandrov __vlan_flush(vg); 1053f409d0edSNikolay Aleksandrov RCU_INIT_POINTER(port->vlgrp, NULL); 1054f409d0edSNikolay Aleksandrov synchronize_rcu(); 1055f409d0edSNikolay Aleksandrov __vlan_group_free(vg); 10565be5a2dfSVlad Yasevich } 1057a60c0903SNikolay Aleksandrov 1058a60c0903SNikolay Aleksandrov void br_vlan_get_stats(const struct net_bridge_vlan *v, 1059a60c0903SNikolay Aleksandrov struct br_vlan_stats *stats) 1060a60c0903SNikolay Aleksandrov { 1061a60c0903SNikolay Aleksandrov int i; 1062a60c0903SNikolay Aleksandrov 1063a60c0903SNikolay Aleksandrov memset(stats, 0, sizeof(*stats)); 1064a60c0903SNikolay Aleksandrov for_each_possible_cpu(i) { 1065a60c0903SNikolay Aleksandrov u64 rxpackets, rxbytes, txpackets, txbytes; 1066a60c0903SNikolay Aleksandrov struct br_vlan_stats *cpu_stats; 1067a60c0903SNikolay Aleksandrov unsigned int start; 1068a60c0903SNikolay Aleksandrov 1069a60c0903SNikolay Aleksandrov cpu_stats = per_cpu_ptr(v->stats, i); 1070a60c0903SNikolay Aleksandrov do { 1071a60c0903SNikolay Aleksandrov start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); 1072a60c0903SNikolay Aleksandrov rxpackets = cpu_stats->rx_packets; 1073a60c0903SNikolay Aleksandrov rxbytes = cpu_stats->rx_bytes; 1074a60c0903SNikolay Aleksandrov txbytes = cpu_stats->tx_bytes; 1075a60c0903SNikolay Aleksandrov txpackets = cpu_stats->tx_packets; 1076a60c0903SNikolay Aleksandrov } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); 1077a60c0903SNikolay Aleksandrov 1078a60c0903SNikolay Aleksandrov stats->rx_packets += rxpackets; 1079a60c0903SNikolay Aleksandrov stats->rx_bytes += rxbytes; 1080a60c0903SNikolay Aleksandrov stats->tx_bytes += txbytes; 1081a60c0903SNikolay Aleksandrov stats->tx_packets += txpackets; 1082a60c0903SNikolay Aleksandrov } 1083a60c0903SNikolay Aleksandrov } 1084