netdev_upper_dev_unlink(real_dev, dev); /* Because unregister_netdevice_queue() makes sure at least one rcu *graceperiodisrespectedbeforedevicefreeing, *wedontneedtocallsynchronize_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);
}
if (real_dev->features & NETIF_F_VLAN_CHALLENGED ||
real_dev->type != ARPHRD_ETHER) {
pr_info("VLANs not supported on %s\n", name);
NL_SET_ERR_MSG_MOD(extack, "VLANs not supported on device"); return -EOPNOTSUPP;
}
/* So, got the sucker initialized, now lets place *itintoourlocalstructure.
*/
vlan_group_set_device(grp, vlan->vlan_proto, vlan_id, dev);
grp->nr_vlan_devs++;
/* Gotta set up the fields for the device. */ switch (vn->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. *Namewilllooklike: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. *Namewilllooklike: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. *Namewilllooklike:vlan0005
*/ default:
snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id);
}
/* May be called without an actual change */ if (ether_addr_equal(vlan->real_dev_addr, dev->dev_addr)) return;
/* vlan continues to inherit address of lower device */ if (vlan_dev_inherit_address(vlandev, dev)) goto out;
/* vlan address was different from the old address and is equal to
* the new address */ if (!ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) &&
ether_addr_equal(vlandev->dev_addr, dev->dev_addr))
dev_uc_del(dev, vlandev->dev_addr);
/* vlan address was equal to the old address and is different from
* the new address */ if (ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) &&
!ether_addr_equal(vlandev->dev_addr, dev->dev_addr))
dev_uc_add(dev, vlandev->dev_addr);
if (is_vlan_dev(dev)) { int err = __vlan_device_event(dev, event);
if (err) return notifier_from_errno(err);
}
if (event == NETDEV_UP)
vlan_vid0_add(dev); elseif (event == NETDEV_DOWN)
vlan_vid0_del(dev);
vlan_info = rtnl_dereference(dev->vlan_info); if (!vlan_info) goto out;
grp = &vlan_info->grp;
/* It is OK that we do not hold the group lock right now, *aswerunundertheRTNLlock.
*/
switch (event) { case NETDEV_CHANGE: /* Propagate real device state to vlan devices */
vlan_group_for_each_dev(grp, i, vlandev)
vlan_stacked_transfer_operstate(dev, vlandev,
vlan_dev_priv(vlandev)); break;
case NETDEV_CHANGEADDR: /* Adjust unicast filters on underlying device */
vlan_group_for_each_dev(grp, i, vlandev) {
flgs = vlandev->flags; if (!(flgs & IFF_UP)) continue;
vlan_sync_address(dev, vlandev);
} break;
case NETDEV_CHANGEMTU:
vlan_group_for_each_dev(grp, i, vlandev) { if (vlandev->mtu <= dev->mtu) continue;
dev_set_mtu(vlandev, dev->mtu);
} break;
case NETDEV_FEAT_CHANGE: /* Propagate device features to underlying device */
vlan_group_for_each_dev(grp, i, vlandev)
vlan_transfer_features(dev, vlandev); break;
case NETDEV_DOWN: { struct net_device *tmp;
LIST_HEAD(close_list);
/* Put all VLANs for this dev in the down state too. */
vlan_group_for_each_dev(grp, i, vlandev) {
flgs = vlandev->flags; if (!(flgs & IFF_UP)) continue;
vlan = vlan_dev_priv(vlandev); if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
list_add(&vlandev->close_list, &close_list);
}
netif_close_many(&close_list, false);
list_for_each_entry_safe(vlandev, tmp, &close_list, close_list) {
vlan_stacked_transfer_operstate(dev, vlandev,
vlan_dev_priv(vlandev));
list_del_init(&vlandev->close_list);
}
list_del(&close_list); break;
} case NETDEV_UP: /* Put all VLANs for this dev in the up state too. */
vlan_group_for_each_dev(grp, i, vlandev) {
flgs = netif_get_flags(vlandev); if (flgs & IFF_UP) continue;
case NETDEV_UNREGISTER: /* twiddle thumbs on netns device moves */ if (dev->reg_state != NETREG_UNREGISTERING) break;
vlan_group_for_each_dev(grp, i, vlandev) { /* removal of last vid destroys vlan_info, abort
* afterwards */ if (vlan_info->nr_vids == 1)
last = true;
unregister_vlan_dev(vlandev, &list); if (last) break;
}
unregister_netdevice_many(&list); break;
case NETDEV_PRE_TYPE_CHANGE: /* Forbid underlaying device to change its type. */ if (vlan_uses_dev(dev)) return NOTIFY_BAD; break;
case NETDEV_NOTIFY_PEERS: case NETDEV_BONDING_FAILOVER: case NETDEV_RESEND_IGMP: /* Propagate to vlan devices */
vlan_group_for_each_dev(grp, i, vlandev)
call_netdevice_notifiers(event, vlandev); break;
case NETDEV_CVLAN_FILTER_PUSH_INFO:
err = vlan_filter_push_vids(vlan_info, htons(ETH_P_8021Q)); if (err) return notifier_from_errno(err); break;
case NETDEV_CVLAN_FILTER_DROP_INFO:
vlan_filter_drop_vids(vlan_info, htons(ETH_P_8021Q)); break;
case NETDEV_SVLAN_FILTER_PUSH_INFO:
err = vlan_filter_push_vids(vlan_info, htons(ETH_P_8021AD)); if (err) return notifier_from_errno(err); break;
case NETDEV_SVLAN_FILTER_DROP_INFO:
vlan_filter_drop_vids(vlan_info, htons(ETH_P_8021AD)); break;
}
if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args))) return -EFAULT;
/* Null terminate this sucker, just in case. */
args.device1[sizeof(args.device1) - 1] = 0;
args.u.device2[sizeof(args.u.device2) - 1] = 0;
rtnl_lock();
switch (args.cmd) { case SET_VLAN_INGRESS_PRIORITY_CMD: case SET_VLAN_EGRESS_PRIORITY_CMD: case SET_VLAN_FLAG_CMD: case ADD_VLAN_CMD: case DEL_VLAN_CMD: case GET_VLAN_REALDEV_NAME_CMD: case GET_VLAN_VID_CMD:
err = -ENODEV;
dev = __dev_get_by_name(net, args.device1); if (!dev) goto out;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.