/* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */ int vlan_dev_set_vlan_flag(char *dev_name, __u32 flag, short flag_val) { struct net_device *dev = dev_get_by_name(dev_name); if (dev) { if (dev->priv_flags & IFF_802_1Q_VLAN) { /* verify flag is supported */ if (flag == 1) { if (flag_val) { VLAN_DEV_INFO(dev)->flags |= 1; } else { VLAN_DEV_INFO(dev)->flags &= ~1; } dev_put(dev); return 0; } else { printk(KERN_ERR "%s: flag %i is not valid.\n", __FUNCTION__, (int)(flag)); dev_put(dev); return -EINVAL; } } else { printk(KERN_ERR "%s: %s is not a vlan device, priv_flags: %hX.\n", __FUNCTION__, dev->name, dev->priv_flags); dev_put(dev); } } else { printk(KERN_ERR "%s: Could not find device: %s\n", __FUNCTION__, dev_name); } return -EINVAL; }
/* * Delete directory entry for VLAN device. */ int vlan_proc_rem_dev(struct net_device *vlandev) { if (!vlandev) { printk(VLAN_ERR "%s: invalid argument: %p\n", __FUNCTION__, vlandev); return -EINVAL; } if (!(vlandev->priv_flags & IFF_802_1Q_VLAN)) { printk(VLAN_DBG "%s: invalid argument, device: %s is not a VLAN device, priv_flags: 0x%4hX.\n", __FUNCTION__, vlandev->name, vlandev->priv_flags); return -EINVAL; } #ifdef VLAN_DEBUG printk(VLAN_DBG "%s: dev: %p\n", __FUNCTION__, vlandev); #endif /** NOTE: This will consume the memory pointed to by dent, it seems. */ if (VLAN_DEV_INFO(vlandev)->dent) { remove_proc_entry(VLAN_DEV_INFO(vlandev)->dent->name, proc_vlan_dir); VLAN_DEV_INFO(vlandev)->dent = NULL; } return 0; }
int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_device_stats *stats = vlan_dev_get_stats(dev); struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); /* Handle non-VLAN frames if they are sent to us, for example by DHCP. * * NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... */ if (veth->h_vlan_proto != __constant_htons(ETH_P_8021Q)) { int orig_headroom = skb_headroom(skb); unsigned short veth_TCI; /* This is not a VLAN frame...but we can fix that! */ VLAN_DEV_INFO(dev)->cnt_encap_on_xmit++; #ifdef VLAN_DEBUG printk(VLAN_DBG "%s: proto to encap: 0x%hx (hbo)\n", __FUNCTION__, htons(veth->h_vlan_proto)); #endif /* Construct the second two bytes. This field looks something * like: * usr_priority: 3 bits (high bits) * CFI 1 bit * VLAN ID 12 bits (low bits) */ veth_TCI = VLAN_DEV_INFO(dev)->vlan_id; veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); skb = __vlan_put_tag(skb, veth_TCI); if (!skb) { stats->tx_dropped++; return 0; } if (orig_headroom < VLAN_HLEN) { VLAN_DEV_INFO(dev)->cnt_inc_headroom_on_tx++; } } #ifdef VLAN_DEBUG printk(VLAN_DBG "%s: about to send skb: %p to dev: %s\n", __FUNCTION__, skb, skb->dev->name); printk(VLAN_DBG " %2hx.%2hx.%2hx.%2xh.%2hx.%2hx %2hx.%2hx.%2hx.%2hx.%2hx.%2hx %4hx %4hx %4hx\n", veth->h_dest[0], veth->h_dest[1], veth->h_dest[2], veth->h_dest[3], veth->h_dest[4], veth->h_dest[5], veth->h_source[0], veth->h_source[1], veth->h_source[2], veth->h_source[3], veth->h_source[4], veth->h_source[5], veth->h_vlan_proto, veth->h_vlan_TCI, veth->h_vlan_encapsulated_proto); #endif stats->tx_packets++; /* for statics only */ stats->tx_bytes += skb->len; skb->dev = VLAN_DEV_INFO(dev)->real_dev; dev_queue_xmit(skb); return 0; }
s32 netmode_br_transparent_rcv_finish(struct sk_buff *skb, int (*okfn)(struct sk_buff *)) { struct iphdr *iph; u32 br_ip; netmode_skb_header_revert(skb); if(skb->protocol == ETH_P_PPP_SES) { skb_push(skb, skb->data - skb->mac.raw - 14); skb_xmit(skb); return NF_STOLEN; } if(ETH_P_IP != skb->protocol || 0 != br_get_ip(skb, &br_ip)) { goto BR_CONTINUE; } if(0 == br_ip) { if(skb->dev->priv_flags & IFF_802_1Q_VLAN) { skb = conplat_vlan_skb_recv_put_tag(skb, VLAN_DEV_INFO(skb->dev)->vlan_id); } skb_xmit(skb); return NF_STOLEN; } iph = skb->nh.iph; if (likely(iph->saddr != br_ip && iph->daddr != br_ip && (u32)WEBAUTH_SERVER_ADDR_U32 != iph->saddr && (u32)WEBAUTH_SERVER_ADDR_U32 != iph->daddr) ) { if ( skb->dev->priv_flags&IFF_802_1Q_VLAN ) { skb = conplat_vlan_skb_recv_put_tag(skb, VLAN_DEV_INFO(skb->dev)->vlan_id); } skb_xmit(skb); return NF_STOLEN; } BR_CONTINUE: NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,okfn,-349); return NF_STOLEN; }
/* Flags are defined in the vlan_flags enum in include/linux/if_vlan.h file. */ int vlan_dev_set_vlan_flag(const struct net_device *dev, u32 flag, short flag_val) { /* verify flag is supported */ if (flag == VLAN_FLAG_REORDER_HDR) { if (flag_val) { VLAN_DEV_INFO(dev)->flags |= VLAN_FLAG_REORDER_HDR; } else { VLAN_DEV_INFO(dev)->flags &= ~VLAN_FLAG_REORDER_HDR; } return 0; } printk(KERN_ERR "%s: flag %i is not valid.\n", __FUNCTION__, flag); return -EINVAL; }
int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; struct ifreq ifrr; int err = -EOPNOTSUPP; strncpy(ifrr.ifr_name, real_dev->name, IFNAMSIZ); ifrr.ifr_ifru = ifr->ifr_ifru; switch(cmd) { case SIOCGMIIPHY: case SIOCGMIIREG: case SIOCSMIIREG: if (real_dev->do_ioctl && netif_device_present(real_dev)) err = real_dev->do_ioctl(real_dev, &ifrr, cmd); break; case SIOCETHTOOL: err = dev_ethtool(&ifrr); } if (!err) ifr->ifr_ifru = ifrr.ifr_ifru; return err; }
int vlan_dev_open(struct net_device *dev) { if (!(VLAN_DEV_INFO(dev)->real_dev->flags & IFF_UP)) return -ENETDOWN; return 0; }
int vlan_proc_add_dev (struct net_device *vlandev) { struct vlan_dev_info *dev_info = VLAN_DEV_INFO(vlandev); if (!(vlandev->priv_flags & IFF_802_1Q_VLAN)) { printk(KERN_ERR "ERROR: vlan_proc_add, device -:%s:- is NOT a VLAN\n", vlandev->name); return -EINVAL; } dev_info->dent = create_proc_entry(vlandev->name, S_IFREG|S_IRUSR|S_IWUSR, proc_vlan_dir); if (!dev_info->dent) return -ENOBUFS; dev_info->dent->proc_fops = &vlandev_fops; dev_info->dent->data = vlandev; #ifdef VLAN_DEBUG printk(KERN_ERR "vlan_proc_add, device -:%s:- being added.\n", vlandev->name); #endif return 0; }
int vlan_dev_get_vid(const char *dev_name, unsigned short* result) { struct net_device *dev = dev_get_by_name(dev_name); int rv = 0; if (dev) { if (dev->priv_flags & IFF_802_1Q_VLAN) { *result = VLAN_DEV_INFO(dev)->vlan_id; dev_put(dev); rv = 0; } else { /*printk(KERN_ERR "%s: %s is not a vlan device, priv_flags: %hX.\n", __FUNCTION__, dev->name, dev->priv_flags);*/ dev_put(dev); rv = -EINVAL; } } else { /* printk(KERN_ERR "%s: Could not find device: %s\n", __FUNCTION__, dev_name);*/ rv = -ENODEV; } return rv; }
/* Cleanup all vlan devices * Note: devices that have been registered that but not * brought up will exist but have no module ref count. */ static void __exit vlan_cleanup_devices(void) { struct net_device *dev, *nxt; rtnl_lock(); for (dev = dev_base; dev; dev = nxt) { nxt = dev->next; if (dev->priv_flags & IFF_802_1Q_VLAN) { unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev, VLAN_DEV_INFO(dev)->vlan_id); unregister_netdevice(dev); } } rtnl_unlock(); }
static int vlandev_seq_show(struct seq_file *seq, void *offset) { struct net_device *vlandev = (struct net_device *) seq->private; const struct vlan_dev_info *dev_info = VLAN_DEV_INFO(vlandev); struct net_device_stats *stats; static const char fmt[] = "%30s %12lu\n"; static const char fmt_bytes[] = "%30s %20llu\n"; static const char fmt_pkt[] = "%30s %16llu\n"; int i; if (!(vlandev->priv_flags & IFF_802_1Q_VLAN)) return 0; seq_printf(seq, "%s VID: %d REORDER_HDR: %i dev->priv_flags: %hx\n", vlandev->name, dev_info->vlan_id, (int)(dev_info->flags & 1), vlandev->priv_flags); stats = vlan_dev_get_stats(vlandev); seq_printf(seq, fmt_pkt, "total frames received", stats->rx_packets); seq_printf(seq, fmt_bytes, "total bytes received", stats->rx_bytes); seq_printf(seq, fmt, "Broadcast/Multicast Rcvd", stats->multicast); seq_puts(seq, "\n"); seq_printf(seq, fmt_pkt, "total frames transmitted", stats->tx_packets); seq_printf(seq, fmt_bytes, "total bytes transmitted", stats->tx_bytes); seq_printf(seq, fmt, "total headroom inc", dev_info->cnt_inc_headroom_on_tx); seq_printf(seq, fmt, "total encap on xmit", dev_info->cnt_encap_on_xmit); seq_printf(seq, "Device: %s", dev_info->real_dev->name); /* now show all PRIORITY mappings relating to this VLAN */ seq_printf(seq, "\nINGRESS priority mappings: 0:%u 1:%u 2:%u 3:%u 4:%u 5:%u 6:%u 7:%u\n", dev_info->ingress_priority_map[0], dev_info->ingress_priority_map[1], dev_info->ingress_priority_map[2], dev_info->ingress_priority_map[3], dev_info->ingress_priority_map[4], dev_info->ingress_priority_map[5], dev_info->ingress_priority_map[6], dev_info->ingress_priority_map[7]); seq_printf(seq, "EGRESSS priority Mappings: "); for (i = 0; i < 16; i++) { const struct vlan_priority_tci_mapping *mp = dev_info->egress_priority_map[i]; while (mp) { seq_printf(seq, "%u:%hu ", mp->priority, ((mp->vlan_qos >> 13) & 0x7)); mp = mp->next; } } seq_puts(seq, "\n"); return 0; }
int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_device_stats *stats = vlan_dev_get_stats(dev); struct vlan_skb_tx_cookie *cookie; stats->tx_packets++; stats->tx_bytes += skb->len; skb->dev = VLAN_DEV_INFO(dev)->real_dev; cookie = VLAN_TX_SKB_CB(skb); cookie->magic = VLAN_TX_COOKIE_MAGIC; cookie->vlan_tag = (VLAN_DEV_INFO(dev)->vlan_id | vlan_dev_get_egress_qos_mask(dev, skb)); dev_queue_xmit(skb); return 0; }
void vlan_change_rx_flags(struct net_device *dev, int change) { struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; if (change & IFF_ALLMULTI) dev_set_allmulti(real_dev, dev->flags & IFF_ALLMULTI ? 1 : -1); if (change & IFF_PROMISC) dev_set_promiscuity(real_dev, dev->flags & IFF_PROMISC ? 1 : -1); }
int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) { /* TODO: gotta make sure the underlying layer can handle it, * maybe an IFF_VLAN_CAPABLE flag for devices? */ if (VLAN_DEV_INFO(dev)->real_dev->mtu < new_mtu) return -ERANGE; dev->mtu = new_mtu; return 0; }
static void vlan_flush_mc_list(struct net_device *dev) { struct dev_mc_list *dmi = dev->mc_list; while (dmi) { printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from vlan interface\n", dev->name, dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2], dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]); dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); dmi = dev->mc_list; } /* dev->mc_list is NULL by the time we get here. */ vlan_destroy_mc_list(VLAN_DEV_INFO(dev)->old_mc_list); VLAN_DEV_INFO(dev)->old_mc_list = NULL; }
void vlan_dev_set_ingress_priority(const struct net_device *dev, u32 skb_prio, short vlan_prio) { struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev); if (vlan->ingress_priority_map[vlan_prio & 0x7] && !skb_prio) vlan->nr_ingress_mappings--; else if (!vlan->ingress_priority_map[vlan_prio & 0x7] && skb_prio) vlan->nr_ingress_mappings++; vlan->ingress_priority_map[vlan_prio & 0x7] = skb_prio; }
void vlan_dev_destruct(struct net_device *dev) { if (dev) { vlan_flush_mc_list(dev); if (dev->priv) { if (VLAN_DEV_INFO(dev)->dent) BUG(); kfree(dev->priv); dev->priv = NULL; } } }
static int unregister_vlan_device(const char *vlan_IF_name) { struct net_device *dev = NULL; int ret; dev = dev_get_by_name(vlan_IF_name); ret = -EINVAL; if (dev) { if (dev->priv_flags & IFF_802_1Q_VLAN) { rtnl_lock(); ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev, VLAN_DEV_INFO(dev)->vlan_id); dev_put(dev); unregister_netdevice(dev); rtnl_unlock(); if (ret == 1) ret = 0; } else { printk(VLAN_ERR "%s: ERROR: Tried to remove a non-vlan device " "with VLAN code, name: %s priv_flags: %hX\n", __FUNCTION__, dev->name, dev->priv_flags); dev_put(dev); ret = -EPERM; } } else { #ifdef VLAN_DEBUG printk(VLAN_DBG "%s: WARNING: Could not find dev.\n", __FUNCTION__); #endif ret = -EINVAL; } return ret; }
int vlan_dev_set_egress_priority(char *dev_name, __u32 skb_prio, short vlan_prio) { struct net_device *dev = dev_get_by_name(dev_name); struct vlan_priority_tci_mapping *mp = NULL; struct vlan_priority_tci_mapping *np; if (dev) { if (dev->priv_flags & IFF_802_1Q_VLAN) { /* See if a priority mapping exists.. */ mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF]; while (mp) { if (mp->priority == skb_prio) { mp->vlan_qos = ((vlan_prio << 13) & 0xE000); dev_put(dev); return 0; } mp = mp->next; } /* Create a new mapping then. */ mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF]; np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL); if (np) { np->next = mp; np->priority = skb_prio; np->vlan_qos = ((vlan_prio << 13) & 0xE000); VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF] = np; dev_put(dev); return 0; } else { dev_put(dev); return -ENOBUFS; } } dev_put(dev); } return -EINVAL; }
static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) { if (VLAN_DEV_INFO(skb->dev)->flags & 1) { skb = skb_share_check(skb, GFP_ATOMIC); if (skb) { /* Lifted from Gleb's VLAN code... */ memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 12); skb->mac.raw += VLAN_HLEN; } } return skb; }
int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_device_stats *stats = vlan_dev_get_stats(dev); unsigned short veth_TCI; /* Construct the second two bytes. This field looks something * like: * usr_priority: 3 bits (high bits) * CFI 1 bit * VLAN ID 12 bits (low bits) */ veth_TCI = VLAN_DEV_INFO(dev)->vlan_id; veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb); skb = __vlan_hwaccel_put_tag(skb, veth_TCI); stats->tx_packets++; stats->tx_bytes += skb->len; skb->dev = VLAN_DEV_INFO(dev)->real_dev; dev_queue_xmit(skb); return 0; }
int vlan_dev_stop(struct net_device *dev) { struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; dev_mc_unsync(real_dev, dev); if (dev->flags & IFF_ALLMULTI) dev_set_allmulti(real_dev, -1); if (dev->flags & IFF_PROMISC) dev_set_promiscuity(real_dev, -1); if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len); return 0; }
int vlan_dev_set_ingress_priority(char *dev_name, __u32 skb_prio, short vlan_prio) { struct net_device *dev = dev_get_by_name(dev_name); if (dev) { if (dev->priv_flags & IFF_802_1Q_VLAN) { /* see if a priority mapping exists.. */ VLAN_DEV_INFO(dev)->ingress_priority_map[vlan_prio & 0x7] = skb_prio; dev_put(dev); return 0; } dev_put(dev); } return -EINVAL; }
static inline unsigned short vlan_dev_get_egress_qos_mask(struct net_device* dev, struct sk_buff* skb) { struct vlan_priority_tci_mapping *mp = VLAN_DEV_INFO(dev)->egress_priority_map[(skb->priority & 0xF)]; while (mp) { if (mp->priority == skb->priority) { return mp->vlan_qos; /* This should already be shifted to mask * correctly with the VLAN's TCI */ } mp = mp->next; } return 0; }
int vlan_dev_get_vid(const char *dev_name, unsigned short* result) { struct net_device *dev = dev_get_by_name(dev_name); int rv = 0; if (dev) { if (dev->priv_flags & IFF_802_1Q_VLAN) { *result = VLAN_DEV_INFO(dev)->vlan_id; rv = 0; } else { rv = -EINVAL; } dev_put(dev); } else { rv = -ENODEV; } return rv; }
int vlan_dev_get_realdev_name(const char *dev_name, char* result) { struct net_device *dev = dev_get_by_name(dev_name); int rv = 0; if (dev) { if (dev->priv_flags & IFF_802_1Q_VLAN) { strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23); rv = 0; } else { rv = -EINVAL; } dev_put(dev); } else { rv = -ENODEV; } return rv; }
static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) { if (VLAN_DEV_INFO(skb->dev)->flags & 1) { if (skb_shared(skb) || skb_cloned(skb)) { struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); kfree_skb(skb); skb = nskb; } if (skb) { /* Lifted from Gleb's VLAN code... */ memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 12); skb->mac_header += VLAN_HLEN; } } return skb; }
static int vlan_dev_init(struct net_device *dev) { struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; /* IFF_BROADCAST|IFF_MULTICAST; ??? */ dev->flags = real_dev->flags & ~IFF_UP; dev->iflink = real_dev->ifindex; dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))) | (1<<__LINK_STATE_PRESENT); /* TODO: maybe just assign it to be ETHERNET? */ dev->type = real_dev->type; #if defined (CONFIG_RAETH_TSO) #if defined(CONFIG_RALINK_MT7620) if( (*(volatile u32 *)(0xB000000C) & 0xf) >= 0x5) { dev->features = real_dev->features; } #else /* make pseudo interface has same capacity like real interface */ dev->features = real_dev->features; #endif #endif memcpy(dev->broadcast, real_dev->broadcast, real_dev->addr_len); memcpy(dev->dev_addr, real_dev->dev_addr, real_dev->addr_len); dev->addr_len = real_dev->addr_len; if (real_dev->features & NETIF_F_HW_VLAN_TX) { dev->hard_header = real_dev->hard_header; dev->hard_header_len = real_dev->hard_header_len; dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit; dev->rebuild_header = real_dev->rebuild_header; } else { dev->hard_header = vlan_dev_hard_header; dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN; dev->hard_start_xmit = vlan_dev_hard_start_xmit; dev->rebuild_header = vlan_dev_rebuild_header; } dev->hard_header_parse = real_dev->hard_header_parse; lockdep_set_class(&dev->_xmit_lock, &vlan_netdev_xmit_lock_key); return 0; }
struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh, struct net_device *dev) { struct l2t_entry *e; struct l2t_data *d = L2DATA(cdev); u32 addr = *(u32 *) neigh->primary_key; int ifidx = neigh->dev->ifindex; int hash = arp_hash(addr, ifidx, d); struct port_info *p = netdev_priv(dev); int smt_idx = p->port_id; write_lock_bh(&d->lock); for (e = d->l2tab[hash].first; e; e = e->next) if (e->addr == addr && e->ifindex == ifidx && e->smt_idx == smt_idx) { l2t_hold(d, e); if (atomic_read(&e->refcnt) == 1) reuse_entry(e, neigh); goto done; } /* Need to allocate a new entry */ e = alloc_l2e(d); if (e) { spin_lock(&e->lock); /* avoid race with t3_l2t_free */ e->next = d->l2tab[hash].first; d->l2tab[hash].first = e; e->state = L2T_STATE_RESOLVING; e->addr = addr; e->ifindex = ifidx; e->smt_idx = smt_idx; atomic_set(&e->refcnt, 1); neigh_replace(e, neigh); if (neigh->dev->priv_flags & IFF_802_1Q_VLAN) e->vlan = VLAN_DEV_INFO(neigh->dev)->vlan_id; else e->vlan = VLAN_NONE; spin_unlock(&e->lock); } done: write_unlock_bh(&d->lock); return e; }
static int vlan_seq_show(struct seq_file *seq, void *v) { if (v == SEQ_START_TOKEN) { const char *nmtype = NULL; seq_puts(seq, "VLAN Dev name | VLAN ID\n"); if (vlan_name_type < ARRAY_SIZE(vlan_name_type_str)) nmtype = vlan_name_type_str[vlan_name_type]; seq_printf(seq, "Name-Type: %s\n", nmtype ? nmtype : "UNKNOWN" ); } else { const struct net_device *vlandev = v; const struct vlan_dev_info *dev_info = VLAN_DEV_INFO(vlandev); seq_printf(seq, "%-15s| %d | %s\n", vlandev->name, dev_info->vlan_id, dev_info->real_dev->name); } return 0; }