static void #else static int #endif ospriv_vlan_kill_vid(struct net_device *dev, unsigned short vid) { osif_dev *osifp = ath_netdev_priv(dev); if (osifp->vlgrp != NULL) { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20) #if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) vlan_group_set_device(osifp->vlgrp, vid, NULL); #else osifp->vlgrp = NULL; osifp->vlanID = 0; #endif #else osifp->vlgrp->vlan_devices[vid] = NULL; #endif } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) osifp->vlanID = 0; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) return 0; #endif }
void unregister_vlan_dev(struct net_device *dev, struct list_head *head) { struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct net_device *real_dev = vlan->real_dev; struct vlan_info *vlan_info; struct vlan_group *grp; u16 vlan_id = vlan->vlan_id; ASSERT_RTNL(); vlan_info = rtnl_dereference(real_dev->vlan_info); BUG_ON(!vlan_info); grp = &vlan_info->grp; if (vlan_id) vlan_vid_del(real_dev, vlan_id); grp->nr_vlan_devs--; if (vlan->flags & VLAN_FLAG_GVRP) vlan_gvrp_request_leave(dev); vlan_group_set_device(grp, vlan_id, NULL); unregister_netdevice_queue(dev, head); if (grp->nr_vlan_devs == 0) vlan_gvrp_uninit_applicant(real_dev); dev_put(real_dev); }
static void #else static int #endif __adf_net_vlan_del(struct net_device *dev, unsigned short vid) { __adf_softc_t *sc = netdev_to_softc(dev); if(!sc->vlgrp) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) return 1; #else return; #endif } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,20) sc->vlgrp->vlan_devices[vid] = NULL; #else #if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) vlan_group_set_device(sc->vlgrp, vid, NULL); #endif #endif sc->vid = 0; sc->vlgrp = NULL ; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) return 0; #endif }
int register_vlan_dev(struct net_device *dev) { struct vlan_dev_info *vlan = vlan_dev_info(dev); struct net_device *real_dev = vlan->real_dev; const struct net_device_ops *ops = real_dev->netdev_ops; u16 vlan_id = vlan->vlan_id; struct vlan_group *grp, *ngrp = NULL; int err; grp = rtnl_dereference(real_dev->vlgrp); if (!grp) { ngrp = grp = vlan_group_alloc(real_dev); if (!grp) return -ENOBUFS; err = vlan_gvrp_init_applicant(real_dev); if (err < 0) goto out_free_group; } err = vlan_group_prealloc_vid(grp, vlan_id); if (err < 0) goto out_uninit_applicant; err = register_netdevice(dev); if (err < 0) goto out_uninit_applicant; /* Account for reference in struct vlan_dev_info */ dev_hold(real_dev); netif_stacked_transfer_operstate(real_dev, dev); linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */ /* So, got the sucker initialized, now lets place * it into our local structure. */ vlan_group_set_device(grp, vlan_id, dev); grp->nr_vlans++; if (ngrp) { if (ops->ndo_vlan_rx_register) ops->ndo_vlan_rx_register(real_dev, ngrp); rcu_assign_pointer(real_dev->vlgrp, ngrp); } if (real_dev->features & NETIF_F_HW_VLAN_FILTER) ops->ndo_vlan_rx_add_vid(real_dev, vlan_id); return 0; out_uninit_applicant: if (ngrp) vlan_gvrp_uninit_applicant(real_dev); out_free_group: if (ngrp) { /* Free the group, after all cpu's are done. */ call_rcu(&ngrp->rcu, vlan_rcu_free); } return err; }
int register_vlan_dev(struct net_device *dev) { struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct net_device *real_dev = vlan->real_dev; u16 vlan_id = vlan->vlan_id; struct vlan_info *vlan_info; struct vlan_group *grp; int err; err = vlan_vid_add(real_dev, vlan_id); if (err) return err; vlan_info = rtnl_dereference(real_dev->vlan_info); /* vlan_info should be there now. vlan_vid_add took care of it */ BUG_ON(!vlan_info); grp = &vlan_info->grp; if (grp->nr_vlan_devs == 0) { err = vlan_gvrp_init_applicant(real_dev); if (err < 0) goto out_vid_del; } err = vlan_group_prealloc_vid(grp, vlan_id); if (err < 0) goto out_uninit_applicant; err = register_netdevice(dev); if (err < 0) goto out_uninit_applicant; /* Account for reference in struct vlan_dev_priv */ dev_hold(real_dev); netif_stacked_transfer_operstate(real_dev, dev); linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */ /* So, got the sucker initialized, now lets place * it into our local structure. */ vlan_group_set_device(grp, vlan_id, dev); grp->nr_vlan_devs++; return 0; out_uninit_applicant: if (grp->nr_vlan_devs == 0) vlan_gvrp_uninit_applicant(real_dev); out_vid_del: vlan_vid_del(real_dev, vlan_id); return err; }
int register_vlan_dev(struct net_device *dev) { struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct net_device *real_dev = vlan->real_dev; u16 vlan_id = vlan->vlan_id; struct vlan_info *vlan_info; struct vlan_group *grp; int err; err = vlan_vid_add(real_dev, vlan_id); if (err) return err; vlan_info = rtnl_dereference(real_dev->vlan_info); BUG_ON(!vlan_info); grp = &vlan_info->grp; if (grp->nr_vlan_devs == 0) { err = vlan_gvrp_init_applicant(real_dev); if (err < 0) goto out_vid_del; } err = vlan_group_prealloc_vid(grp, vlan_id); if (err < 0) goto out_uninit_applicant; err = register_netdevice(dev); if (err < 0) goto out_uninit_applicant; dev_hold(real_dev); netif_stacked_transfer_operstate(real_dev, dev); linkwatch_fire_event(dev); vlan_group_set_device(grp, vlan_id, dev); grp->nr_vlan_devs++; return 0; out_uninit_applicant: if (grp->nr_vlan_devs == 0) vlan_gvrp_uninit_applicant(real_dev); out_vid_del: vlan_vid_del(real_dev, vlan_id); return err; }
void unregister_vlan_dev(struct net_device *dev, struct list_head *head) { struct vlan_dev_info *vlan = vlan_dev_info(dev); struct net_device *real_dev = vlan->real_dev; const struct net_device_ops *ops = real_dev->netdev_ops; struct vlan_group *grp; u16 vlan_id = vlan->vlan_id; ASSERT_RTNL(); grp = rtnl_dereference(real_dev->vlgrp); BUG_ON(!grp); /* Take it out of our own structures, but be sure to interlock with * HW accelerating devices or SW vlan input packet processing if * VLAN is not 0 (leave it there for 802.1p). */ if (vlan_id && (real_dev->features & NETIF_F_HW_VLAN_FILTER)) ops->ndo_vlan_rx_kill_vid(real_dev, vlan_id); grp->nr_vlans--; if (vlan->flags & VLAN_FLAG_GVRP) vlan_gvrp_request_leave(dev); vlan_group_set_device(grp, vlan_id, NULL); /* Because unregister_netdevice_queue() makes sure at least one rcu * grace period is respected before device freeing, * we dont need to call synchronize_net() here. */ unregister_netdevice_queue(dev, head); /* If the group is now empty, kill off the group. */ if (grp->nr_vlans == 0) { vlan_gvrp_uninit_applicant(real_dev); rcu_assign_pointer(real_dev->vlgrp, NULL); if (ops->ndo_vlan_rx_register) ops->ndo_vlan_rx_register(real_dev, NULL); /* Free the group, after all cpu's are done. */ call_rcu(&grp->rcu, vlan_rcu_free); } /* Get rid of the vlan's reference to real_dev */ dev_put(real_dev); }
void unregister_vlan_dev(struct net_device *dev, struct list_head *head) { struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct net_device *real_dev = vlan->real_dev; struct vlan_info *vlan_info; struct vlan_group *grp; u16 vlan_id = vlan->vlan_id; ASSERT_RTNL(); vlan_info = rtnl_dereference(real_dev->vlan_info); BUG_ON(!vlan_info); grp = &vlan_info->grp; grp->nr_vlan_devs--; if (vlan->flags & VLAN_FLAG_MVRP) vlan_mvrp_request_leave(dev); if (vlan->flags & VLAN_FLAG_GVRP) vlan_gvrp_request_leave(dev); vlan_group_set_device(grp, vlan->vlan_proto, vlan_id, NULL); netdev_upper_dev_unlink(real_dev, dev); /* Because unregister_netdevice_queue() makes sure at least one rcu * grace period is respected before device freeing, * we dont need to call synchronize_net() here. */ unregister_netdevice_queue(dev, head); if (grp->nr_vlan_devs == 0) { vlan_mvrp_uninit_applicant(real_dev); vlan_gvrp_uninit_applicant(real_dev); } /* Take it out of our own structures, but be sure to interlock with * HW accelerating devices or SW vlan input packet processing if * VLAN is not 0 (leave it there for 802.1p). */ if (vlan_id) vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id); /* Get rid of the vlan's reference to real_dev */ dev_put(real_dev); }
/* Attach a VLAN device to a mac address (ie Ethernet Card). * Returns the device that was created, or NULL if there was * an error of some kind. */ static struct net_device *register_vlan_device(const char *eth_IF_name, unsigned short VLAN_ID) { struct vlan_group *grp, *ngrp = NULL; struct net_device *new_dev; struct net_device *real_dev; /* the ethernet device */ char name[IFNAMSIZ]; #ifdef VLAN_DEBUG printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n", __FUNCTION__, eth_IF_name, VLAN_ID); #endif if (VLAN_ID >= VLAN_VID_MASK) goto out_ret_null; /* find the device relating to eth_IF_name. */ real_dev = dev_get_by_name(eth_IF_name); if (!real_dev) goto out_ret_null; if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { printk(VLAN_DBG "%s: VLANs not supported on %s.\n", __FUNCTION__, real_dev->name); goto out_put_dev; } if ((real_dev->features & NETIF_F_HW_VLAN_RX) && (real_dev->vlan_rx_register == NULL || real_dev->vlan_rx_kill_vid == NULL)) { printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", __FUNCTION__, real_dev->name); goto out_put_dev; } if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) && (real_dev->vlan_rx_add_vid == NULL || real_dev->vlan_rx_kill_vid == NULL)) { printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", __FUNCTION__, real_dev->name); goto out_put_dev; } /* From this point on, all the data structures must remain * consistent. */ rtnl_lock(); /* The real device must be up and operating in order to * assosciate a VLAN device with it. */ if (!(real_dev->flags & IFF_UP)) goto out_unlock; if (find_vlan_dev(real_dev, VLAN_ID) != NULL) { /* was already registered. */ printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__); goto out_unlock; } /* Gotta set up the fields for the device. */ #ifdef VLAN_DEBUG printk(VLAN_DBG "About to allocate name, vlan_name_type: %i\n", vlan_name_type); #endif switch (vlan_name_type) { case VLAN_NAME_TYPE_RAW_PLUS_VID: /* name will look like: eth1.0005 */ snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, VLAN_ID); break; case VLAN_NAME_TYPE_PLUS_VID_NO_PAD: /* Put our vlan.VID in the name. * Name will look like: vlan5 */ snprintf(name, IFNAMSIZ, "vlan%i", VLAN_ID); break; case VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD: /* Put our vlan.VID in the name. * Name will look like: eth0.5 */ snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, VLAN_ID); break; case VLAN_NAME_TYPE_PLUS_VID: /* Put our vlan.VID in the name. * Name will look like: vlan0005 */ default: snprintf(name, IFNAMSIZ, "vlan%.4i", VLAN_ID); }; new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name, vlan_setup); if (new_dev == NULL) goto out_unlock; /* need 4 bytes for extra VLAN header info, * hope the underlying device can handle it. */ new_dev->mtu = real_dev->mtu; #ifdef VLAN_DEBUG printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name); VLAN_MEM_DBG("new_dev->priv malloc, addr: %p size: %i\n", new_dev->priv, sizeof(struct vlan_dev_info)); #endif memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len); memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len); new_dev->addr_len = real_dev->addr_len; if (real_dev->features & NETIF_F_HW_VLAN_TX) { new_dev->hard_header = real_dev->hard_header; new_dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit; new_dev->rebuild_header = real_dev->rebuild_header; } else { new_dev->hard_header = vlan_dev_hard_header; new_dev->hard_start_xmit = vlan_dev_hard_start_xmit; new_dev->rebuild_header = vlan_dev_rebuild_header; } new_dev->hard_header_parse = real_dev->hard_header_parse; VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */ VLAN_DEV_INFO(new_dev)->real_dev = real_dev; VLAN_DEV_INFO(new_dev)->dent = NULL; VLAN_DEV_INFO(new_dev)->flags = 1; #ifdef VLAN_DEBUG printk(VLAN_DBG "About to go find the group for idx: %i\n", real_dev->ifindex); #endif grp = vlan_find_group(real_dev->ifindex); if (!grp) { ngrp = grp = vlan_group_alloc(real_dev->ifindex); if (!grp) goto out_free_newdev; } if (register_netdevice(new_dev)) goto out_free_group; vlan_transfer_operstate(real_dev, new_dev); linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */ /* So, got the sucker initialized, now lets place * it into our local structure. */ if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX) real_dev->vlan_rx_register(real_dev, ngrp); vlan_group_set_device(grp, VLAN_ID, new_dev); if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */ printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n", new_dev->name); if (real_dev->features & NETIF_F_HW_VLAN_FILTER) real_dev->vlan_rx_add_vid(real_dev, VLAN_ID); rtnl_unlock(); #ifdef VLAN_DEBUG printk(VLAN_DBG "Allocated new device successfully, returning.\n"); #endif return new_dev; out_free_group: if (ngrp) vlan_group_free(ngrp); out_free_newdev: free_netdev(new_dev); out_unlock: rtnl_unlock(); out_put_dev: dev_put(real_dev); out_ret_null: return NULL; }
/* This returns 0 if everything went fine. * It will return 1 if the group was killed as a result. * A negative return indicates failure. * * The RTNL lock must be held. */ static int unregister_vlan_dev(struct net_device *real_dev, unsigned short vlan_id) { struct net_device *dev = NULL; int real_dev_ifindex = real_dev->ifindex; struct vlan_group *grp; int i, ret; #ifdef VLAN_DEBUG printk(VLAN_DBG "%s: VID: %i\n", __FUNCTION__, vlan_id); #endif /* sanity check */ if (vlan_id >= VLAN_VID_MASK) return -EINVAL; ASSERT_RTNL(); grp = vlan_find_group(real_dev_ifindex); ret = 0; if (grp) { dev = vlan_group_get_device(grp, vlan_id); if (dev) { /* Remove proc entry */ vlan_proc_rem_dev(dev); /* Take it out of our own structures, but be sure to * interlock with HW accelerating devices or SW vlan * input packet processing. */ if (real_dev->features & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER)) { real_dev->vlan_rx_kill_vid(real_dev, vlan_id); } vlan_group_set_device(grp, vlan_id, NULL); synchronize_net(); /* Caller unregisters (and if necessary, puts) * VLAN device, but we get rid of the reference to * real_dev here. */ dev_put(real_dev); /* If the group is now empty, kill off the * group. */ for (i = 0; i < VLAN_VID_MASK; i++) if (vlan_group_get_device(grp, i)) break; if (i == VLAN_VID_MASK) { if (real_dev->features & NETIF_F_HW_VLAN_RX) real_dev->vlan_rx_register(real_dev, NULL); hlist_del_rcu(&grp->hlist); /* Free the group, after all cpu's are done. */ call_rcu(&grp->rcu, vlan_rcu_free); grp = NULL; ret = 1; } } } return ret; }