vlan.c revision d84430702496f617c01c5e2d27d0e82e02390bb7
1a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/* 2a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * lib/route/link/vlan.c VLAN Link Info 3a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 4a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * This library is free software; you can redistribute it and/or 5a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * modify it under the terms of the GNU Lesser General Public 6a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * License as published by the Free Software Foundation version 2.1 7a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * of the License. 8a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 10a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf */ 11a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 12a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/** 13a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * @ingroup link_info 14a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * @defgroup vlan VLAN 15a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * @brief 16a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 17a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * @{ 18a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf */ 19a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 20a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include <netlink-local.h> 21a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include <netlink/netlink.h> 22a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include <netlink/attr.h> 23a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include <netlink/utils.h> 24a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include <netlink/object.h> 25a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include <netlink/route/rtnl.h> 26a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include <netlink/route/link/info-api.h> 27a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include <netlink/route/link/vlan.h> 28a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 29a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include <linux/if_vlan.h> 30a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 31a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/** @cond SKIP */ 32a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#define VLAN_HAS_ID (1<<0) 33a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#define VLAN_HAS_FLAGS (1<<1) 34a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#define VLAN_HAS_INGRESS_QOS (1<<2) 35a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#define VLAN_HAS_EGRESS_QOS (1<<3) 36a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 37a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstruct vlan_info 38a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 39a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf uint16_t vi_vlan_id; 40a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf uint32_t vi_flags; 41a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf uint32_t vi_flags_mask; 42a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf uint32_t vi_ingress_qos[VLAN_PRIO_MAX+1]; 43a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf uint32_t vi_negress; 44a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf uint32_t vi_egress_size; 45a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_map * vi_egress_qos; 46a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf uint32_t vi_mask; 47a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf}; 48a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/** @endcond */ 49a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 50a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic struct trans_tbl vlan_flags[] = { 51a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf __ADD(VLAN_FLAG_REORDER_HDR, reorder_hdr) 52a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf}; 53a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 54a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafchar *rtnl_link_vlan_flags2str(int flags, char *buf, size_t len) 55a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 56a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return __flags2str(flags, buf, len, vlan_flags, ARRAY_SIZE(vlan_flags)); 57a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 58a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 59a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafint rtnl_link_vlan_str2flags(const char *name) 60a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 61a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return __str2flags(name, vlan_flags, ARRAY_SIZE(vlan_flags)); 62a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 63a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 64a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic struct nla_policy vlan_policy[IFLA_VLAN_MAX+1] = { 65a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf [IFLA_VLAN_ID] = { .type = NLA_U16 }, 66a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf [IFLA_VLAN_FLAGS] = { .minlen = sizeof(struct ifla_vlan_flags) }, 67a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf [IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED }, 68a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf [IFLA_VLAN_EGRESS_QOS] = { .type = NLA_NESTED }, 69a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf}; 70a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 71a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic int vlan_alloc(struct rtnl_link *link) 72a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 73a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi; 74a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 75a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if ((vi = calloc(1, sizeof(*vi))) == NULL) 768a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 77a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 78a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf link->l_info = vi; 79a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 80a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return 0; 81a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 82a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 83a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic int vlan_parse(struct rtnl_link *link, struct nlattr *data, 84a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct nlattr *xstats) 85a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 86a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct nlattr *tb[IFLA_VLAN_MAX+1]; 87a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi; 88a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf int err; 89a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 90a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf NL_DBG(3, "Parsing VLAN link info"); 91a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 92a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if ((err = nla_parse_nested(tb, IFLA_VLAN_MAX, data, vlan_policy)) < 0) 93a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf goto errout; 94a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 95a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if ((err = vlan_alloc(link)) < 0) 96a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf goto errout; 97a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 98a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi = link->l_info; 99a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 100a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (tb[IFLA_VLAN_ID]) { 101a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_vlan_id = nla_get_u16(tb[IFLA_VLAN_ID]); 102a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_mask |= VLAN_HAS_ID; 103a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 104a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 105a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (tb[IFLA_VLAN_FLAGS]) { 106a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct ifla_vlan_flags flags; 107a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf nla_memcpy(&flags, tb[IFLA_VLAN_FLAGS], sizeof(flags)); 108a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 109a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_flags = flags.flags; 110a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_mask |= VLAN_HAS_FLAGS; 111a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 112a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 113a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (tb[IFLA_VLAN_INGRESS_QOS]) { 114a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct ifla_vlan_qos_mapping *map; 115a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct nlattr *nla; 116a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf int remaining; 117a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 118a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf memset(vi->vi_ingress_qos, 0, sizeof(vi->vi_ingress_qos)); 119a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 120a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf nla_for_each_nested(nla, tb[IFLA_VLAN_INGRESS_QOS], remaining) { 121a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (nla_len(nla) < sizeof(*map)) 1228a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 123a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 124a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf map = nla_data(nla); 125a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (map->from < 0 || map->from > VLAN_PRIO_MAX) { 1268a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 127a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 128a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 129a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_ingress_qos[map->from] = map->to; 130a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 131a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 132a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_mask |= VLAN_HAS_INGRESS_QOS; 133a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 134a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 135a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (tb[IFLA_VLAN_EGRESS_QOS]) { 136a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct ifla_vlan_qos_mapping *map; 137a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct nlattr *nla; 138a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf int remaining, i = 0; 139a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 140a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf nla_for_each_nested(nla, tb[IFLA_VLAN_EGRESS_QOS], remaining) { 141a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (nla_len(nla) < sizeof(*map)) 1428a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 143a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf i++; 144a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 145a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 146a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf /* align to have a little reserve */ 147a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_egress_size = (i + 32) & ~31; 148a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_egress_qos = calloc(vi->vi_egress_size, sizeof(*map)); 149a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi->vi_egress_qos == NULL) 1508a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 151a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 152a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf i = 0; 153a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf nla_for_each_nested(nla, tb[IFLA_VLAN_EGRESS_QOS], remaining) { 154a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf map = nla_data(nla); 155a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf NL_DBG(4, "Assigning egress qos mapping %d\n", i); 156a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_egress_qos[i].vm_from = map->from; 157a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_egress_qos[i++].vm_to = map->to; 158a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 159a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 160a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_negress = i; 161a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_mask |= VLAN_HAS_EGRESS_QOS; 162a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 163a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 164a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf err = 0; 165a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graferrout: 166a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return err; 167a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 168a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 169a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic void vlan_free(struct rtnl_link *link) 170a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 171a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi = link->l_info; 172a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 173a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi) { 174a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf free(vi->vi_egress_qos); 175a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_egress_qos = NULL; 176a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 177a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 178a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf free(vi); 179a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf link->l_info = NULL; 180a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 181a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 182d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void vlan_dump_line(struct rtnl_link *link, struct nl_dump_params *p) 183a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 184a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi = link->l_info; 185a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 186d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "vlan-id %d", vi->vi_vlan_id); 187a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 188a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 189d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void vlan_dump_details(struct rtnl_link *link, struct nl_dump_params *p) 190a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 191a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi = link->l_info; 192a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf int i, printed; 193a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf char buf[64]; 194a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 195a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf rtnl_link_vlan_flags2str(vi->vi_flags, buf, sizeof(buf)); 196d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, " vlan-info id %d <%s>\n", vi->vi_vlan_id, buf); 197a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 198a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi->vi_mask & VLAN_HAS_INGRESS_QOS) { 199d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, 200a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf " ingress vlan prio -> qos/socket prio mapping:\n"); 201a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf for (i = 0, printed = 0; i <= VLAN_PRIO_MAX; i++) { 202a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi->vi_ingress_qos[i]) { 203d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf if (printed == 0) 204d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, " "); 205d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "%x -> %#08x, ", 206a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf i, vi->vi_ingress_qos[i]); 207a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (printed++ == 3) { 208d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "\n"); 209a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf printed = 0; 210a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 211a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 212a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 213a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 214a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (printed > 0 && printed != 4) 215d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "\n"); 216a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 217a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 218a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) { 219d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, 220a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf " egress qos/socket prio -> vlan prio mapping:\n"); 221a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf for (i = 0, printed = 0; i < vi->vi_negress; i++) { 222d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf if (printed == 0) 223d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump_line(p, " "); 224d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "%#08x -> %x, ", 225a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_egress_qos[i].vm_from, 226a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_egress_qos[i].vm_to); 227a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (printed++ == 3) { 228d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "\n"); 229a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf printed = 0; 230a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 231a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 232a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 233a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (printed > 0 && printed != 4) 234d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "\n"); 235a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 236a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 237a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 238a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic int vlan_clone(struct rtnl_link *dst, struct rtnl_link *src) 239a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 240a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vdst, *vsrc = src->l_info; 241a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf int err; 242a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 243a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf dst->l_info = NULL; 244a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if ((err = rtnl_link_set_info_type(dst, "vlan")) < 0) 245a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return err; 246a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vdst = dst->l_info; 247a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 248a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vdst->vi_egress_qos = calloc(vsrc->vi_egress_size, 249a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf sizeof(struct vlan_map)); 250a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (!vdst->vi_egress_qos) 2518a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 252a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 253a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf memcpy(vdst->vi_egress_qos, vsrc->vi_egress_qos, 254a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vsrc->vi_egress_size * sizeof(struct vlan_map)); 255a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 256a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return 0; 257a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 258a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 259a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link) 260a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 261a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi = link->l_info; 262a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct nlattr *data; 263a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 264a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) 2658a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MSGSIZE; 266a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 267a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi->vi_mask & VLAN_HAS_ID) 268a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf NLA_PUT_U16(msg, IFLA_VLAN_ID, vi->vi_vlan_id); 269a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 270a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi->vi_mask & VLAN_HAS_FLAGS) { 271a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct ifla_vlan_flags flags = { 272a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf .flags = vi->vi_flags, 273a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf .mask = vi->vi_flags_mask, 274a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf }; 275a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 276a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf NLA_PUT(msg, IFLA_VLAN_FLAGS, sizeof(flags), &flags); 277a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 278a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 279a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi->vi_mask & VLAN_HAS_INGRESS_QOS) { 280a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct ifla_vlan_qos_mapping map; 281a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct nlattr *qos; 282a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf int i; 283a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 284a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS))) 285a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf goto nla_put_failure; 286a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 287a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf for (i = 0; i <= VLAN_PRIO_MAX; i++) { 288a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi->vi_ingress_qos[i]) { 289a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf map.from = i; 290a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf map.to = vi->vi_ingress_qos[i]; 291a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 292a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf NLA_PUT(msg, i, sizeof(map), &map); 293a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 294a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 295a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 296a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf nla_nest_end(msg, qos); 297a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 298a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 299a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) { 300a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct ifla_vlan_qos_mapping map; 301a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct nlattr *qos; 302a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf int i; 303a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 304a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS))) 305a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf goto nla_put_failure; 306a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 307a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf for (i = 0; i < vi->vi_negress; i++) { 308a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf map.from = vi->vi_egress_qos[i].vm_from; 309a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf map.to = vi->vi_egress_qos[i].vm_to; 310a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 311a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf NLA_PUT(msg, i, sizeof(map), &map); 312a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 313a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 314a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf nla_nest_end(msg, qos); 315a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 316a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 317a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf nla_nest_end(msg, data); 318a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 319a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafnla_put_failure: 320a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 321a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return 0; 322a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 323a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 324a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic struct rtnl_link_info_ops vlan_info_ops = { 325a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf .io_name = "vlan", 326a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf .io_alloc = vlan_alloc, 327a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf .io_parse = vlan_parse, 328d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf .io_dump = { 329d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_LINE] = vlan_dump_line, 330d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_DETAILS] = vlan_dump_details, 331d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf }, 332a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf .io_clone = vlan_clone, 333ddbe8f6c417ddba11f32e1f36bbfbdee8a598a36Thomas Graf .io_put_attrs = vlan_put_attrs, 334a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf .io_free = vlan_free, 335a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf}; 336a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 337a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafint rtnl_link_vlan_set_id(struct rtnl_link *link, int id) 338a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 339a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi = link->l_info; 340a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 341a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) 3428a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_OPNOTSUPP; 343a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 344a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_vlan_id = id; 345a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_mask |= VLAN_HAS_ID; 346a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 347a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return 0; 348a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 349a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 350a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafint rtnl_link_vlan_get_id(struct rtnl_link *link) 351a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 352a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi = link->l_info; 353a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 354a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) 3558a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_OPNOTSUPP; 356a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 357a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi->vi_mask & VLAN_HAS_ID) 358a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return vi->vi_vlan_id; 359a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf else 360a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return 0; 361a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 362a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 363a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafint rtnl_link_vlan_set_flags(struct rtnl_link *link, unsigned int flags) 364a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 365a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi = link->l_info; 366a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 367a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) 3688a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_OPNOTSUPP; 369a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 370a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_flags_mask |= flags; 371a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_flags |= flags; 372a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_mask |= VLAN_HAS_FLAGS; 373a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 374a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return 0; 375a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 376a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 377a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafint rtnl_link_vlan_unset_flags(struct rtnl_link *link, unsigned int flags) 378a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 379a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi = link->l_info; 380a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 381a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) 3828a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_OPNOTSUPP; 383a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 384a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_flags_mask |= flags; 385a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_flags &= ~flags; 386a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_mask |= VLAN_HAS_FLAGS; 387a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 388a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return 0; 389a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 390a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 391a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafunsigned int rtnl_link_vlan_get_flags(struct rtnl_link *link) 392a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 393a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi = link->l_info; 394a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 395a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) 3968a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_OPNOTSUPP; 397a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 398a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return vi->vi_flags; 399a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 400a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 401a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafint rtnl_link_vlan_set_ingress_map(struct rtnl_link *link, int from, 402a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf uint32_t to) 403a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 404a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi = link->l_info; 405a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 406a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) 4078a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_OPNOTSUPP; 408a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 409a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (from < 0 || from > VLAN_PRIO_MAX) 4108a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 411a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 412a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_ingress_qos[from] = to; 413a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_mask |= VLAN_HAS_INGRESS_QOS; 414a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 415a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return 0; 416a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 417a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 418a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafuint32_t *rtnl_link_vlan_get_ingress_map(struct rtnl_link *link) 419a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 420a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi = link->l_info; 421a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 4228a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) 423a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return NULL; 424a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 425a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi->vi_mask & VLAN_HAS_INGRESS_QOS) 426a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return vi->vi_ingress_qos; 427a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf else 428a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return NULL; 429a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 430a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 431a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafint rtnl_link_vlan_set_egress_map(struct rtnl_link *link, uint32_t from, int to) 432a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 433a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi = link->l_info; 434a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 435a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) 4368a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_OPNOTSUPP; 437a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 438a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (to < 0 || to > VLAN_PRIO_MAX) 4398a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 440a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 441a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi->vi_negress >= vi->vi_egress_size) { 442a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf int new_size = vi->vi_egress_size + 32; 443a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf void *ptr; 444a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 445a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf ptr = realloc(vi->vi_egress_qos, new_size); 446a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (!ptr) 4478a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 448a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 449a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_egress_qos = ptr; 450a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_egress_size = new_size; 451a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 452a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 453a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_egress_qos[vi->vi_negress].vm_from = from; 454a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_egress_qos[vi->vi_negress].vm_to = to; 455a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_negress++; 456a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf vi->vi_mask |= VLAN_HAS_EGRESS_QOS; 457a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 458a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return 0; 459a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 460a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 461a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstruct vlan_map *rtnl_link_vlan_get_egress_map(struct rtnl_link *link, 462a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf int *negress) 463a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 464a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf struct vlan_info *vi = link->l_info; 465a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 4668a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if (link->l_info_ops != &vlan_info_ops || !link->l_info_ops) 467a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return NULL; 468a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 4698a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if (negress == NULL) 470a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return NULL; 471a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 472a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) { 473a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *negress = vi->vi_negress; 474a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return vi->vi_egress_qos; 475a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } else { 476a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *negress = 0; 477a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return NULL; 478a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 479a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 480a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 481a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic void __init vlan_init(void) 482a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 483a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf rtnl_link_register_info(&vlan_info_ops); 484a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 485a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 486a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic void __exit vlan_exit(void) 487a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 488a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf rtnl_link_unregister_info(&vlan_info_ops); 489a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 490a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 491a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/** @} */ 492