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 67a37b85c9SVlad Yasevich /* Called under RCU */ 68a37b85c9SVlad Yasevich bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, 69a37b85c9SVlad Yasevich struct sk_buff *skb) 70a37b85c9SVlad Yasevich { 71a37b85c9SVlad Yasevich u16 vid; 72a37b85c9SVlad Yasevich 73a37b85c9SVlad Yasevich /* If VLAN filtering is disabled on the bridge, all packets are 74a37b85c9SVlad Yasevich * permitted. 75a37b85c9SVlad Yasevich */ 76a37b85c9SVlad Yasevich if (!br->vlan_enabled) 77a37b85c9SVlad Yasevich return true; 78a37b85c9SVlad Yasevich 79a37b85c9SVlad Yasevich /* If there are no vlan in the permitted list, all packets are 80a37b85c9SVlad Yasevich * rejected. 81a37b85c9SVlad Yasevich */ 82a37b85c9SVlad Yasevich if (!v) 83a37b85c9SVlad Yasevich return false; 84a37b85c9SVlad Yasevich 85a37b85c9SVlad Yasevich br_vlan_get_tag(skb, &vid); 86a37b85c9SVlad Yasevich if (test_bit(vid, v->vlan_bitmap)) 87a37b85c9SVlad Yasevich return true; 88a37b85c9SVlad Yasevich 89a37b85c9SVlad Yasevich return false; 90a37b85c9SVlad Yasevich } 91a37b85c9SVlad Yasevich 9285f46c6bSVlad Yasevich /* Called under RCU. */ 9385f46c6bSVlad Yasevich bool br_allowed_egress(struct net_bridge *br, 9485f46c6bSVlad Yasevich const struct net_port_vlans *v, 9585f46c6bSVlad Yasevich const struct sk_buff *skb) 9685f46c6bSVlad Yasevich { 9785f46c6bSVlad Yasevich u16 vid; 9885f46c6bSVlad Yasevich 9985f46c6bSVlad Yasevich if (!br->vlan_enabled) 10085f46c6bSVlad Yasevich return true; 10185f46c6bSVlad Yasevich 10285f46c6bSVlad Yasevich if (!v) 10385f46c6bSVlad Yasevich return false; 10485f46c6bSVlad Yasevich 10585f46c6bSVlad Yasevich br_vlan_get_tag(skb, &vid); 10685f46c6bSVlad Yasevich if (test_bit(vid, v->vlan_bitmap)) 10785f46c6bSVlad Yasevich return true; 10885f46c6bSVlad Yasevich 10985f46c6bSVlad Yasevich return false; 11085f46c6bSVlad Yasevich } 11185f46c6bSVlad Yasevich 112243a2e63SVlad Yasevich /* Must be protected by RTNL */ 113243a2e63SVlad Yasevich int br_vlan_add(struct net_bridge *br, u16 vid) 114243a2e63SVlad Yasevich { 115243a2e63SVlad Yasevich struct net_port_vlans *pv = NULL; 116243a2e63SVlad Yasevich int err; 117243a2e63SVlad Yasevich 118243a2e63SVlad Yasevich ASSERT_RTNL(); 119243a2e63SVlad Yasevich 120243a2e63SVlad Yasevich pv = rtnl_dereference(br->vlan_info); 121243a2e63SVlad Yasevich if (pv) 122243a2e63SVlad Yasevich return __vlan_add(pv, vid); 123243a2e63SVlad Yasevich 124243a2e63SVlad Yasevich /* Create port vlan infomration 125243a2e63SVlad Yasevich */ 126243a2e63SVlad Yasevich pv = kzalloc(sizeof(*pv), GFP_KERNEL); 127243a2e63SVlad Yasevich if (!pv) 128243a2e63SVlad Yasevich return -ENOMEM; 129243a2e63SVlad Yasevich 130243a2e63SVlad Yasevich pv->parent.br = br; 131243a2e63SVlad Yasevich err = __vlan_add(pv, vid); 132243a2e63SVlad Yasevich if (err) 133243a2e63SVlad Yasevich goto out; 134243a2e63SVlad Yasevich 135243a2e63SVlad Yasevich rcu_assign_pointer(br->vlan_info, pv); 136243a2e63SVlad Yasevich return 0; 137243a2e63SVlad Yasevich out: 138243a2e63SVlad Yasevich kfree(pv); 139243a2e63SVlad Yasevich return err; 140243a2e63SVlad Yasevich } 141243a2e63SVlad Yasevich 142243a2e63SVlad Yasevich /* Must be protected by RTNL */ 143243a2e63SVlad Yasevich int br_vlan_delete(struct net_bridge *br, u16 vid) 144243a2e63SVlad Yasevich { 145243a2e63SVlad Yasevich struct net_port_vlans *pv; 146243a2e63SVlad Yasevich 147243a2e63SVlad Yasevich ASSERT_RTNL(); 148243a2e63SVlad Yasevich 149243a2e63SVlad Yasevich pv = rtnl_dereference(br->vlan_info); 150243a2e63SVlad Yasevich if (!pv) 151243a2e63SVlad Yasevich return -EINVAL; 152243a2e63SVlad Yasevich 153243a2e63SVlad Yasevich __vlan_del(pv, vid); 154243a2e63SVlad Yasevich return 0; 155243a2e63SVlad Yasevich } 156243a2e63SVlad Yasevich 157243a2e63SVlad Yasevich void br_vlan_flush(struct net_bridge *br) 158243a2e63SVlad Yasevich { 159243a2e63SVlad Yasevich struct net_port_vlans *pv; 160243a2e63SVlad Yasevich 161243a2e63SVlad Yasevich ASSERT_RTNL(); 162243a2e63SVlad Yasevich 163243a2e63SVlad Yasevich pv = rtnl_dereference(br->vlan_info); 164243a2e63SVlad Yasevich if (!pv) 165243a2e63SVlad Yasevich return; 166243a2e63SVlad Yasevich 167243a2e63SVlad Yasevich __vlan_flush(pv); 168243a2e63SVlad Yasevich } 169243a2e63SVlad Yasevich 170243a2e63SVlad Yasevich int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 171243a2e63SVlad Yasevich { 172243a2e63SVlad Yasevich if (!rtnl_trylock()) 173243a2e63SVlad Yasevich return restart_syscall(); 174243a2e63SVlad Yasevich 175243a2e63SVlad Yasevich if (br->vlan_enabled == val) 176243a2e63SVlad Yasevich goto unlock; 177243a2e63SVlad Yasevich 178243a2e63SVlad Yasevich br->vlan_enabled = val; 179243a2e63SVlad Yasevich 180243a2e63SVlad Yasevich unlock: 181243a2e63SVlad Yasevich rtnl_unlock(); 182243a2e63SVlad Yasevich return 0; 183243a2e63SVlad Yasevich } 184243a2e63SVlad Yasevich 185243a2e63SVlad Yasevich /* Must be protected by RTNL */ 186243a2e63SVlad Yasevich int nbp_vlan_add(struct net_bridge_port *port, u16 vid) 187243a2e63SVlad Yasevich { 188243a2e63SVlad Yasevich struct net_port_vlans *pv = NULL; 189243a2e63SVlad Yasevich int err; 190243a2e63SVlad Yasevich 191243a2e63SVlad Yasevich ASSERT_RTNL(); 192243a2e63SVlad Yasevich 193243a2e63SVlad Yasevich pv = rtnl_dereference(port->vlan_info); 194243a2e63SVlad Yasevich if (pv) 195243a2e63SVlad Yasevich return __vlan_add(pv, vid); 196243a2e63SVlad Yasevich 197243a2e63SVlad Yasevich /* Create port vlan infomration 198243a2e63SVlad Yasevich */ 199243a2e63SVlad Yasevich pv = kzalloc(sizeof(*pv), GFP_KERNEL); 200243a2e63SVlad Yasevich if (!pv) { 201243a2e63SVlad Yasevich err = -ENOMEM; 202243a2e63SVlad Yasevich goto clean_up; 203243a2e63SVlad Yasevich } 204243a2e63SVlad Yasevich 205243a2e63SVlad Yasevich pv->port_idx = port->port_no; 206243a2e63SVlad Yasevich pv->parent.port = port; 207243a2e63SVlad Yasevich err = __vlan_add(pv, vid); 208243a2e63SVlad Yasevich if (err) 209243a2e63SVlad Yasevich goto clean_up; 210243a2e63SVlad Yasevich 211243a2e63SVlad Yasevich rcu_assign_pointer(port->vlan_info, pv); 212243a2e63SVlad Yasevich return 0; 213243a2e63SVlad Yasevich 214243a2e63SVlad Yasevich clean_up: 215243a2e63SVlad Yasevich kfree(pv); 216243a2e63SVlad Yasevich return err; 217243a2e63SVlad Yasevich } 218243a2e63SVlad Yasevich 219243a2e63SVlad Yasevich /* Must be protected by RTNL */ 220243a2e63SVlad Yasevich int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) 221243a2e63SVlad Yasevich { 222243a2e63SVlad Yasevich struct net_port_vlans *pv; 223243a2e63SVlad Yasevich 224243a2e63SVlad Yasevich ASSERT_RTNL(); 225243a2e63SVlad Yasevich 226243a2e63SVlad Yasevich pv = rtnl_dereference(port->vlan_info); 227243a2e63SVlad Yasevich if (!pv) 228243a2e63SVlad Yasevich return -EINVAL; 229243a2e63SVlad Yasevich 230243a2e63SVlad Yasevich return __vlan_del(pv, vid); 231243a2e63SVlad Yasevich } 232243a2e63SVlad Yasevich 233243a2e63SVlad Yasevich void nbp_vlan_flush(struct net_bridge_port *port) 234243a2e63SVlad Yasevich { 235243a2e63SVlad Yasevich struct net_port_vlans *pv; 236243a2e63SVlad Yasevich 237243a2e63SVlad Yasevich ASSERT_RTNL(); 238243a2e63SVlad Yasevich 239243a2e63SVlad Yasevich pv = rtnl_dereference(port->vlan_info); 240243a2e63SVlad Yasevich if (!pv) 241243a2e63SVlad Yasevich return; 242243a2e63SVlad Yasevich 243243a2e63SVlad Yasevich __vlan_flush(pv); 244243a2e63SVlad Yasevich } 245