15c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy/*
25c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy * iplink_vlan.c	VLAN device support
35c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy *
45c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy *              This program is free software; you can redistribute it and/or
55c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy *              modify it under the terms of the GNU General Public License
65c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy *              as published by the Free Software Foundation; either version
75c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy *              2 of the License, or (at your option) any later version.
85c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy *
95c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy * Authors:     Patrick McHardy <kaber@trash.net>
105c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy */
115c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
125c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy#include <stdio.h>
135c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy#include <stdlib.h>
145c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy#include <string.h>
155c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy#include <linux/if_vlan.h>
165c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
175c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy#include "rt_names.h"
185c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy#include "utils.h"
195c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy#include "ip_common.h"
205c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
21561e650eff679296d3f4c12657721ae769cbc187vadimkstatic void print_explain(FILE *f)
225c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy{
23561e650eff679296d3f4c12657721ae769cbc187vadimk	fprintf(f,
248b47135474cde4f0f8c9991741132b930bf3e192Phil Sutter		"Usage: ... vlan id VLANID\n"
258b47135474cde4f0f8c9991741132b930bf3e192Phil Sutter		"                [ protocol VLANPROTO ]\n"
268b47135474cde4f0f8c9991741132b930bf3e192Phil Sutter		"                [ reorder_hdr { on | off } ]\n"
278b47135474cde4f0f8c9991741132b930bf3e192Phil Sutter		"                [ gvrp { on | off } ]\n"
288b47135474cde4f0f8c9991741132b930bf3e192Phil Sutter		"                [ mvrp { on | off } ]\n"
298b47135474cde4f0f8c9991741132b930bf3e192Phil Sutter		"                [ loose_binding { on | off } ]\n"
308b47135474cde4f0f8c9991741132b930bf3e192Phil Sutter		"                [ ingress-qos-map QOS-MAP ]\n"
318b47135474cde4f0f8c9991741132b930bf3e192Phil Sutter		"                [ egress-qos-map QOS-MAP ]\n"
325c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		"\n"
335c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		"VLANID := 0-4095\n"
348b47135474cde4f0f8c9991741132b930bf3e192Phil Sutter		"VLANPROTO: [ 802.1Q / 802.1ad ]\n"
355c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		"QOS-MAP := [ QOS-MAP ] QOS-MAPPING\n"
365c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		"QOS-MAPPING := FROM:TO\n"
375c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	);
385c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy}
395c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
40561e650eff679296d3f4c12657721ae769cbc187vadimkstatic void explain(void)
41561e650eff679296d3f4c12657721ae769cbc187vadimk{
42561e650eff679296d3f4c12657721ae769cbc187vadimk	print_explain(stderr);
43561e650eff679296d3f4c12657721ae769cbc187vadimk}
44561e650eff679296d3f4c12657721ae769cbc187vadimk
4514645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijkstatic int on_off(const char *msg, const char *arg)
465c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy{
4714645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk	fprintf(stderr, "Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n", msg, arg);
485c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	return -1;
495c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy}
505c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
515c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardystatic int vlan_parse_qos_map(int *argcp, char ***argvp, struct nlmsghdr *n,
525c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			      int attrtype)
535c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy{
545c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	int argc = *argcp;
555c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	char **argv = *argvp;
565c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	struct ifla_vlan_qos_mapping m;
575c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	struct rtattr *tail;
585c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
595c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	tail = NLMSG_TAIL(n);
605c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	addattr_l(n, 1024, attrtype, NULL, 0);
615c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
625c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	while (argc > 0) {
635c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		char *colon = strchr(*argv, ':');
645c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
655c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		if (!colon)
665c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			break;
675c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		*colon = '\0';
685c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
695c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		if (get_u32(&m.from, *argv, 0))
705c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			return 1;
715c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		if (get_u32(&m.to, colon + 1, 0))
725c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			return 1;
735c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		argc--, argv++;
745c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
755c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		addattr_l(n, 1024, IFLA_VLAN_QOS_MAPPING, &m, sizeof(m));
765c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	}
775c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
785c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *)tail;
795c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
805c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	*argcp = argc;
815c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	*argvp = argv;
825c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	return 0;
835c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy}
845c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
855c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardystatic int vlan_parse_opt(struct link_util *lu, int argc, char **argv,
865c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			  struct nlmsghdr *n)
875c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy{
885c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	struct ifla_vlan_flags flags = { 0 };
898fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy	__u16 id, proto;
905c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
915c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	while (argc > 0) {
928fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy		if (matches(*argv, "protocol") == 0) {
938fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy			NEXT_ARG();
948fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy			if (ll_proto_a2n(&proto, *argv))
958fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy				invarg("protocol is invalid", *argv);
968fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy			addattr_l(n, 1024, IFLA_VLAN_PROTOCOL, &proto, 2);
978fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy		} else if (matches(*argv, "id") == 0) {
985c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			NEXT_ARG();
995c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			if (get_u16(&id, *argv, 0))
1005c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy				invarg("id is invalid", *argv);
1015c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			addattr_l(n, 1024, IFLA_VLAN_ID, &id, 2);
1025c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		} else if (matches(*argv, "reorder_hdr") == 0) {
1035c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			NEXT_ARG();
1045c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			flags.mask |= VLAN_FLAG_REORDER_HDR;
1055c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			if (strcmp(*argv, "on") == 0)
1065c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy				flags.flags |= VLAN_FLAG_REORDER_HDR;
1075c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			else if (strcmp(*argv, "off") == 0)
1085c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy				flags.flags &= ~VLAN_FLAG_REORDER_HDR;
1095c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			else
11014645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk				return on_off("reorder_hdr", *argv);
11147420640687cbd389ddd99d39cf7fb0e0bcb265aPatrick McHardy		} else if (matches(*argv, "gvrp") == 0) {
11247420640687cbd389ddd99d39cf7fb0e0bcb265aPatrick McHardy			NEXT_ARG();
11347420640687cbd389ddd99d39cf7fb0e0bcb265aPatrick McHardy			flags.mask |= VLAN_FLAG_GVRP;
11447420640687cbd389ddd99d39cf7fb0e0bcb265aPatrick McHardy			if (strcmp(*argv, "on") == 0)
11547420640687cbd389ddd99d39cf7fb0e0bcb265aPatrick McHardy				flags.flags |= VLAN_FLAG_GVRP;
11647420640687cbd389ddd99d39cf7fb0e0bcb265aPatrick McHardy			else if (strcmp(*argv, "off") == 0)
11747420640687cbd389ddd99d39cf7fb0e0bcb265aPatrick McHardy				flags.flags &= ~VLAN_FLAG_GVRP;
11847420640687cbd389ddd99d39cf7fb0e0bcb265aPatrick McHardy			else
11914645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk				return on_off("gvrp", *argv);
1204e9a686020b2ff4e391f685a53c91365d04a5e43David Ward		} else if (matches(*argv, "mvrp") == 0) {
1214e9a686020b2ff4e391f685a53c91365d04a5e43David Ward			NEXT_ARG();
1224e9a686020b2ff4e391f685a53c91365d04a5e43David Ward			flags.mask |= VLAN_FLAG_MVRP;
1234e9a686020b2ff4e391f685a53c91365d04a5e43David Ward			if (strcmp(*argv, "on") == 0)
1244e9a686020b2ff4e391f685a53c91365d04a5e43David Ward				flags.flags |= VLAN_FLAG_MVRP;
1254e9a686020b2ff4e391f685a53c91365d04a5e43David Ward			else if (strcmp(*argv, "off") == 0)
1264e9a686020b2ff4e391f685a53c91365d04a5e43David Ward				flags.flags &= ~VLAN_FLAG_MVRP;
1274e9a686020b2ff4e391f685a53c91365d04a5e43David Ward			else
1284e9a686020b2ff4e391f685a53c91365d04a5e43David Ward				return on_off("mvrp", *argv);
1292180b6b50bdc50e1a7740e5283930088da0bbae7Patrick McHardy		} else if (matches(*argv, "loose_binding") == 0) {
1302180b6b50bdc50e1a7740e5283930088da0bbae7Patrick McHardy			NEXT_ARG();
1312180b6b50bdc50e1a7740e5283930088da0bbae7Patrick McHardy			flags.mask |= VLAN_FLAG_LOOSE_BINDING;
1322180b6b50bdc50e1a7740e5283930088da0bbae7Patrick McHardy			if (strcmp(*argv, "on") == 0)
1332180b6b50bdc50e1a7740e5283930088da0bbae7Patrick McHardy				flags.flags |= VLAN_FLAG_LOOSE_BINDING;
1342180b6b50bdc50e1a7740e5283930088da0bbae7Patrick McHardy			else if (strcmp(*argv, "off") == 0)
1352180b6b50bdc50e1a7740e5283930088da0bbae7Patrick McHardy				flags.flags &= ~VLAN_FLAG_LOOSE_BINDING;
1362180b6b50bdc50e1a7740e5283930088da0bbae7Patrick McHardy			else
13714645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk				return on_off("loose_binding", *argv);
1385c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		} else if (matches(*argv, "ingress-qos-map") == 0) {
1395c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			NEXT_ARG();
1405c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			if (vlan_parse_qos_map(&argc, &argv, n,
1415c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy					       IFLA_VLAN_INGRESS_QOS))
1425c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy				invarg("invalid ingress-qos-map", *argv);
1435c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			continue;
1445c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		} else if (matches(*argv, "egress-qos-map") == 0) {
1455c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			NEXT_ARG();
1465c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			if (vlan_parse_qos_map(&argc, &argv, n,
1475c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy					       IFLA_VLAN_EGRESS_QOS))
1485c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy				invarg("invalid egress-qos-map", *argv);
1495c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			continue;
1505c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		} else if (matches(*argv, "help") == 0) {
1515c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			explain();
1525c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			return -1;
1535c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		} else {
15414645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk			fprintf(stderr, "vlan: unknown command \"%s\"?\n", *argv);
1555c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			explain();
1565c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			return -1;
1575c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		}
1585c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		argc--, argv++;
1595c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	}
1605c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
1615c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	if (flags.mask)
1625c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		addattr_l(n, 1024, IFLA_VLAN_FLAGS, &flags, sizeof(flags));
1635c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
1645c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	return 0;
1655c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy}
1665c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
16743bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortinstatic void vlan_print_map(FILE *f,
16843bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			   const char *name_json,
16943bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			   const char *name_fp,
17043bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			   struct rtattr *attr)
1715c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy{
1725c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	struct ifla_vlan_qos_mapping *m;
1735c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	struct rtattr *i;
1745c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	int rem;
1755c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
17643bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin	open_json_array(PRINT_JSON, name_json);
17743bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin	print_string(PRINT_FP, NULL, "\n      %s { ", name_fp);
1785c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
1795c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	rem = RTA_PAYLOAD(attr);
1805c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
1815c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		m = RTA_DATA(i);
18243bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin
18343bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin		if (is_json_context()) {
18443bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			open_json_object(NULL);
18543bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			print_uint(PRINT_JSON, "from", NULL, m->from);
18643bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			print_uint(PRINT_JSON, "to", NULL, m->to);
18743bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			close_json_object();
18843bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin		} else {
18943bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			fprintf(f, "%u:%u ", m->from, m->to);
19043bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin		}
1915c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	}
19243bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin
19343bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin	close_json_array(PRINT_JSON, NULL);
19443bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin	print_string(PRINT_FP, NULL, "%s ", "}");
1955c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy}
1965c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
1975c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardystatic void vlan_print_flags(FILE *fp, __u32 flags)
1985c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy{
19943bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin	open_json_array(PRINT_ANY, is_json_context() ? "flags" : "<");
20043bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin#define _PF(f)	if (flags & VLAN_FLAG_##f) {				\
20143bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin		flags &= ~VLAN_FLAG_##f;				\
20243bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin		print_string(PRINT_ANY, NULL, flags ? "%s," : "%s", #f); \
20343bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin	}
2045c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	_PF(REORDER_HDR);
20547420640687cbd389ddd99d39cf7fb0e0bcb265aPatrick McHardy	_PF(GVRP);
2064e9a686020b2ff4e391f685a53c91365d04a5e43David Ward	_PF(MVRP);
2072180b6b50bdc50e1a7740e5283930088da0bbae7Patrick McHardy	_PF(LOOSE_BINDING);
2085c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy#undef _PF
2095c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	if (flags)
21043bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin		print_hex(PRINT_ANY, NULL, "%x", flags);
21143bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin	close_json_array(PRINT_ANY, "> ");
2125c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy}
2135c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
2145c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardystatic void vlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
2155c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy{
2165c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	struct ifla_vlan_flags *flags;
21756f5daac98da0c405fdbc52f04afd5de82404bceStephen Hemminger
2188fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy	SPRINT_BUF(b1);
2198fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy
2205c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	if (!tb)
2215c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		return;
2225c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
2238fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy	if (tb[IFLA_VLAN_PROTOCOL] &&
2248fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy	    RTA_PAYLOAD(tb[IFLA_VLAN_PROTOCOL]) < sizeof(__u16))
2258fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy		return;
2265c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	if (!tb[IFLA_VLAN_ID] ||
2275c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	    RTA_PAYLOAD(tb[IFLA_VLAN_ID]) < sizeof(__u16))
2285c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		return;
2295c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
2308fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy	if (tb[IFLA_VLAN_PROTOCOL])
23143bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin		print_string(PRINT_ANY,
23243bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			     "protocol",
23343bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			     "protocol %s ",
23443bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			     ll_proto_n2a(
23543bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin				     rta_getattr_u16(tb[IFLA_VLAN_PROTOCOL]),
2368fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy				     b1, sizeof(b1)));
2378fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy	else
23843bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin		print_string(PRINT_ANY, "protocol", "protocol %s ", "802.1q");
2398fd8f6ed715aaa6d87e99675e0dfe13ed6c782bdPatric McHardy
24043bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin	print_uint(PRINT_ANY,
24143bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin		   "id",
24243bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin		   "id %u ",
24343bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin		   rta_getattr_u16(tb[IFLA_VLAN_ID]));
2445c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
2455c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	if (tb[IFLA_VLAN_FLAGS]) {
2465c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		if (RTA_PAYLOAD(tb[IFLA_VLAN_FLAGS]) < sizeof(*flags))
2475c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy			return;
2485c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		flags = RTA_DATA(tb[IFLA_VLAN_FLAGS]);
2495c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy		vlan_print_flags(f, flags->flags);
2505c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	}
2515c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	if (tb[IFLA_VLAN_INGRESS_QOS])
25243bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin		vlan_print_map(f,
25343bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			       "ingress_qos",
25443bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			       "ingress-qos-map",
25543bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			       tb[IFLA_VLAN_INGRESS_QOS]);
2565c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	if (tb[IFLA_VLAN_EGRESS_QOS])
25743bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin		vlan_print_map(f,
25843bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			       "egress_qos",
25943bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			       "egress-qos-map",
26043bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			       tb[IFLA_VLAN_EGRESS_QOS]);
2615c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy}
2625c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy
263561e650eff679296d3f4c12657721ae769cbc187vadimkstatic void vlan_print_help(struct link_util *lu, int argc, char **argv,
26443bc20ae736c943a7202fef07104eb1b5800b7f8Julien Fortin			    FILE *f)
265561e650eff679296d3f4c12657721ae769cbc187vadimk{
266561e650eff679296d3f4c12657721ae769cbc187vadimk	print_explain(f);
267561e650eff679296d3f4c12657721ae769cbc187vadimk}
268561e650eff679296d3f4c12657721ae769cbc187vadimk
2695c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardystruct link_util vlan_link_util = {
2705c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	.id		= "vlan",
2715c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	.maxattr	= IFLA_VLAN_MAX,
2725c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	.parse_opt	= vlan_parse_opt,
2735c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy	.print_opt	= vlan_print_opt,
274561e650eff679296d3f4c12657721ae769cbc187vadimk	.print_help	= vlan_print_help,
2755c302d518f10e67ddab9e44207a0c878214ed389Patrick McHardy};
276