1243a2e63SVlad Yasevich #include <linux/kernel.h> 2243a2e63SVlad Yasevich #include <linux/netdevice.h> 3243a2e63SVlad Yasevich #include <linux/rtnetlink.h> 4243a2e63SVlad Yasevich #include <linux/slab.h> 5243a2e63SVlad Yasevich 6243a2e63SVlad Yasevich #include "br_private.h" 7243a2e63SVlad Yasevich 8243a2e63SVlad Yasevich static int __vlan_add(struct net_port_vlans *v, u16 vid) 9243a2e63SVlad Yasevich { 10243a2e63SVlad Yasevich int err; 11243a2e63SVlad Yasevich 12243a2e63SVlad Yasevich if (test_bit(vid, v->vlan_bitmap)) 13243a2e63SVlad Yasevich return -EEXIST; 14243a2e63SVlad Yasevich 15243a2e63SVlad Yasevich if (v->port_idx && vid) { 16243a2e63SVlad Yasevich struct net_device *dev = v->parent.port->dev; 17243a2e63SVlad Yasevich 18243a2e63SVlad Yasevich /* Add VLAN to the device filter if it is supported. 19243a2e63SVlad Yasevich * Stricly speaking, this is not necessary now, since devices 20243a2e63SVlad Yasevich * are made promiscuous by the bridge, but if that ever changes 21243a2e63SVlad Yasevich * this code will allow tagged traffic to enter the bridge. 22243a2e63SVlad Yasevich */ 23243a2e63SVlad Yasevich if (dev->features & NETIF_F_HW_VLAN_FILTER) { 24243a2e63SVlad Yasevich err = dev->netdev_ops->ndo_vlan_rx_add_vid(dev, vid); 25243a2e63SVlad Yasevich if (err) 26243a2e63SVlad Yasevich return err; 27243a2e63SVlad Yasevich } 28243a2e63SVlad Yasevich } 29243a2e63SVlad Yasevich 30243a2e63SVlad Yasevich set_bit(vid, v->vlan_bitmap); 31243a2e63SVlad Yasevich return 0; 32243a2e63SVlad Yasevich } 33243a2e63SVlad Yasevich 34243a2e63SVlad Yasevich static int __vlan_del(struct net_port_vlans *v, u16 vid) 35243a2e63SVlad Yasevich { 36243a2e63SVlad Yasevich if (!test_bit(vid, v->vlan_bitmap)) 37243a2e63SVlad Yasevich return -EINVAL; 38243a2e63SVlad Yasevich 39243a2e63SVlad Yasevich if (v->port_idx && vid) { 40243a2e63SVlad Yasevich struct net_device *dev = v->parent.port->dev; 41243a2e63SVlad Yasevich 42243a2e63SVlad Yasevich if (dev->features & NETIF_F_HW_VLAN_FILTER) 43243a2e63SVlad Yasevich dev->netdev_ops->ndo_vlan_rx_kill_vid(dev, vid); 44243a2e63SVlad Yasevich } 45243a2e63SVlad Yasevich 46243a2e63SVlad Yasevich clear_bit(vid, v->vlan_bitmap); 47243a2e63SVlad Yasevich if (bitmap_empty(v->vlan_bitmap, BR_VLAN_BITMAP_LEN)) { 48243a2e63SVlad Yasevich if (v->port_idx) 49243a2e63SVlad Yasevich rcu_assign_pointer(v->parent.port->vlan_info, NULL); 50243a2e63SVlad Yasevich else 51243a2e63SVlad Yasevich rcu_assign_pointer(v->parent.br->vlan_info, NULL); 52243a2e63SVlad Yasevich kfree_rcu(v, rcu); 53243a2e63SVlad Yasevich } 54243a2e63SVlad Yasevich return 0; 55243a2e63SVlad Yasevich } 56243a2e63SVlad Yasevich 57243a2e63SVlad Yasevich static void __vlan_flush(struct net_port_vlans *v) 58243a2e63SVlad Yasevich { 59243a2e63SVlad Yasevich bitmap_zero(v->vlan_bitmap, BR_VLAN_BITMAP_LEN); 60243a2e63SVlad Yasevich if (v->port_idx) 61243a2e63SVlad Yasevich rcu_assign_pointer(v->parent.port->vlan_info, NULL); 62243a2e63SVlad Yasevich else 63243a2e63SVlad Yasevich rcu_assign_pointer(v->parent.br->vlan_info, NULL); 64243a2e63SVlad Yasevich kfree_rcu(v, rcu); 65243a2e63SVlad Yasevich } 66243a2e63SVlad Yasevich 67243a2e63SVlad Yasevich /* Must be protected by RTNL */ 68243a2e63SVlad Yasevich int br_vlan_add(struct net_bridge *br, u16 vid) 69243a2e63SVlad Yasevich { 70243a2e63SVlad Yasevich struct net_port_vlans *pv = NULL; 71243a2e63SVlad Yasevich int err; 72243a2e63SVlad Yasevich 73243a2e63SVlad Yasevich ASSERT_RTNL(); 74243a2e63SVlad Yasevich 75243a2e63SVlad Yasevich pv = rtnl_dereference(br->vlan_info); 76243a2e63SVlad Yasevich if (pv) 77243a2e63SVlad Yasevich return __vlan_add(pv, vid); 78243a2e63SVlad Yasevich 79243a2e63SVlad Yasevich /* Create port vlan infomration 80243a2e63SVlad Yasevich */ 81243a2e63SVlad Yasevich pv = kzalloc(sizeof(*pv), GFP_KERNEL); 82243a2e63SVlad Yasevich if (!pv) 83243a2e63SVlad Yasevich return -ENOMEM; 84243a2e63SVlad Yasevich 85243a2e63SVlad Yasevich pv->parent.br = br; 86243a2e63SVlad Yasevich err = __vlan_add(pv, vid); 87243a2e63SVlad Yasevich if (err) 88243a2e63SVlad Yasevich goto out; 89243a2e63SVlad Yasevich 90243a2e63SVlad Yasevich rcu_assign_pointer(br->vlan_info, pv); 91243a2e63SVlad Yasevich return 0; 92243a2e63SVlad Yasevich out: 93243a2e63SVlad Yasevich kfree(pv); 94243a2e63SVlad Yasevich return err; 95243a2e63SVlad Yasevich } 96243a2e63SVlad Yasevich 97243a2e63SVlad Yasevich /* Must be protected by RTNL */ 98243a2e63SVlad Yasevich int br_vlan_delete(struct net_bridge *br, u16 vid) 99243a2e63SVlad Yasevich { 100243a2e63SVlad Yasevich struct net_port_vlans *pv; 101243a2e63SVlad Yasevich 102243a2e63SVlad Yasevich ASSERT_RTNL(); 103243a2e63SVlad Yasevich 104243a2e63SVlad Yasevich pv = rtnl_dereference(br->vlan_info); 105243a2e63SVlad Yasevich if (!pv) 106243a2e63SVlad Yasevich return -EINVAL; 107243a2e63SVlad Yasevich 108243a2e63SVlad Yasevich __vlan_del(pv, vid); 109243a2e63SVlad Yasevich return 0; 110243a2e63SVlad Yasevich } 111243a2e63SVlad Yasevich 112243a2e63SVlad Yasevich void br_vlan_flush(struct net_bridge *br) 113243a2e63SVlad Yasevich { 114243a2e63SVlad Yasevich struct net_port_vlans *pv; 115243a2e63SVlad Yasevich 116243a2e63SVlad Yasevich ASSERT_RTNL(); 117243a2e63SVlad Yasevich 118243a2e63SVlad Yasevich pv = rtnl_dereference(br->vlan_info); 119243a2e63SVlad Yasevich if (!pv) 120243a2e63SVlad Yasevich return; 121243a2e63SVlad Yasevich 122243a2e63SVlad Yasevich __vlan_flush(pv); 123243a2e63SVlad Yasevich } 124243a2e63SVlad Yasevich 125243a2e63SVlad Yasevich int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 126243a2e63SVlad Yasevich { 127243a2e63SVlad Yasevich if (!rtnl_trylock()) 128243a2e63SVlad Yasevich return restart_syscall(); 129243a2e63SVlad Yasevich 130243a2e63SVlad Yasevich if (br->vlan_enabled == val) 131243a2e63SVlad Yasevich goto unlock; 132243a2e63SVlad Yasevich 133243a2e63SVlad Yasevich br->vlan_enabled = val; 134243a2e63SVlad Yasevich 135243a2e63SVlad Yasevich unlock: 136243a2e63SVlad Yasevich rtnl_unlock(); 137243a2e63SVlad Yasevich return 0; 138243a2e63SVlad Yasevich } 139243a2e63SVlad Yasevich 140243a2e63SVlad Yasevich /* Must be protected by RTNL */ 141243a2e63SVlad Yasevich int nbp_vlan_add(struct net_bridge_port *port, u16 vid) 142243a2e63SVlad Yasevich { 143243a2e63SVlad Yasevich struct net_port_vlans *pv = NULL; 144243a2e63SVlad Yasevich int err; 145243a2e63SVlad Yasevich 146243a2e63SVlad Yasevich ASSERT_RTNL(); 147243a2e63SVlad Yasevich 148243a2e63SVlad Yasevich pv = rtnl_dereference(port->vlan_info); 149243a2e63SVlad Yasevich if (pv) 150243a2e63SVlad Yasevich return __vlan_add(pv, vid); 151243a2e63SVlad Yasevich 152243a2e63SVlad Yasevich /* Create port vlan infomration 153243a2e63SVlad Yasevich */ 154243a2e63SVlad Yasevich pv = kzalloc(sizeof(*pv), GFP_KERNEL); 155243a2e63SVlad Yasevich if (!pv) { 156243a2e63SVlad Yasevich err = -ENOMEM; 157243a2e63SVlad Yasevich goto clean_up; 158243a2e63SVlad Yasevich } 159243a2e63SVlad Yasevich 160243a2e63SVlad Yasevich pv->port_idx = port->port_no; 161243a2e63SVlad Yasevich pv->parent.port = port; 162243a2e63SVlad Yasevich err = __vlan_add(pv, vid); 163243a2e63SVlad Yasevich if (err) 164243a2e63SVlad Yasevich goto clean_up; 165243a2e63SVlad Yasevich 166243a2e63SVlad Yasevich rcu_assign_pointer(port->vlan_info, pv); 167243a2e63SVlad Yasevich return 0; 168243a2e63SVlad Yasevich 169243a2e63SVlad Yasevich clean_up: 170243a2e63SVlad Yasevich kfree(pv); 171243a2e63SVlad Yasevich return err; 172243a2e63SVlad Yasevich } 173243a2e63SVlad Yasevich 174243a2e63SVlad Yasevich /* Must be protected by RTNL */ 175243a2e63SVlad Yasevich int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) 176243a2e63SVlad Yasevich { 177243a2e63SVlad Yasevich struct net_port_vlans *pv; 178243a2e63SVlad Yasevich 179243a2e63SVlad Yasevich ASSERT_RTNL(); 180243a2e63SVlad Yasevich 181243a2e63SVlad Yasevich pv = rtnl_dereference(port->vlan_info); 182243a2e63SVlad Yasevich if (!pv) 183243a2e63SVlad Yasevich return -EINVAL; 184243a2e63SVlad Yasevich 185243a2e63SVlad Yasevich return __vlan_del(pv, vid); 186243a2e63SVlad Yasevich } 187243a2e63SVlad Yasevich 188243a2e63SVlad Yasevich void nbp_vlan_flush(struct net_bridge_port *port) 189243a2e63SVlad Yasevich { 190243a2e63SVlad Yasevich struct net_port_vlans *pv; 191243a2e63SVlad Yasevich 192243a2e63SVlad Yasevich ASSERT_RTNL(); 193243a2e63SVlad Yasevich 194243a2e63SVlad Yasevich pv = rtnl_dereference(port->vlan_info); 195243a2e63SVlad Yasevich if (!pv) 196243a2e63SVlad Yasevich return; 197243a2e63SVlad Yasevich 198243a2e63SVlad Yasevich __vlan_flush(pv); 199243a2e63SVlad Yasevich } 200