Merge branch 'net-next'
This commit is contained in:
commit
5c2c10b17e
|
|
@ -154,6 +154,8 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
|||
fprintf(fp, "master ");
|
||||
if (r->ndm_flags & NTF_ROUTER)
|
||||
fprintf(fp, "router ");
|
||||
if (r->ndm_flags & NTF_EXT_LEARNED)
|
||||
fprintf(fp, "external ");
|
||||
|
||||
fprintf(fp, "%s\n", state_n2a(r->ndm_state));
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ struct __fdb_entry {
|
|||
|
||||
#define BRIDGE_MODE_VEB 0 /* Default loopback mode */
|
||||
#define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */
|
||||
#define BRIDGE_MODE_UNDEF 0xFFFF /* mode undefined */
|
||||
|
||||
/* Bridge management nested attributes
|
||||
* [IFLA_AF_SPEC] = {
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ enum {
|
|||
IFLA_CARRIER,
|
||||
IFLA_PHYS_PORT_ID,
|
||||
IFLA_CARRIER_CHANGES,
|
||||
IFLA_PHYS_SWITCH_ID,
|
||||
__IFLA_MAX
|
||||
};
|
||||
|
||||
|
|
@ -241,6 +242,8 @@ enum {
|
|||
IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */
|
||||
IFLA_BRPORT_LEARNING, /* mac learning */
|
||||
IFLA_BRPORT_UNICAST_FLOOD, /* flood unicast traffic */
|
||||
IFLA_BRPORT_PROXYARP, /* proxy ARP */
|
||||
IFLA_BRPORT_LEARNING_SYNC, /* mac learning sync from device */
|
||||
__IFLA_BRPORT_MAX
|
||||
};
|
||||
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
|
||||
|
|
@ -327,6 +330,21 @@ enum macvlan_macaddr_mode {
|
|||
|
||||
#define MACVLAN_FLAG_NOPROMISC 1
|
||||
|
||||
/* IPVLAN section */
|
||||
enum {
|
||||
IFLA_IPVLAN_UNSPEC,
|
||||
IFLA_IPVLAN_MODE,
|
||||
__IFLA_IPVLAN_MAX
|
||||
};
|
||||
|
||||
#define IFLA_IPVLAN_MAX (__IFLA_IPVLAN_MAX - 1)
|
||||
|
||||
enum ipvlan_mode {
|
||||
IPVLAN_MODE_L2 = 0,
|
||||
IPVLAN_MODE_L3,
|
||||
IPVLAN_MODE_MAX
|
||||
};
|
||||
|
||||
/* VXLAN section */
|
||||
enum {
|
||||
IFLA_VXLAN_UNSPEC,
|
||||
|
|
|
|||
|
|
@ -22,21 +22,11 @@
|
|||
|
||||
/* Read queue size */
|
||||
#define TUN_READQ_SIZE 500
|
||||
|
||||
/* TUN device flags */
|
||||
#define TUN_TUN_DEV 0x0001
|
||||
#define TUN_TAP_DEV 0x0002
|
||||
/* TUN device type flags: deprecated. Use IFF_TUN/IFF_TAP instead. */
|
||||
#define TUN_TUN_DEV IFF_TUN
|
||||
#define TUN_TAP_DEV IFF_TAP
|
||||
#define TUN_TYPE_MASK 0x000f
|
||||
|
||||
#define TUN_FASYNC 0x0010
|
||||
#define TUN_NOCHECKSUM 0x0020
|
||||
#define TUN_NO_PI 0x0040
|
||||
/* This flag has no real effect */
|
||||
#define TUN_ONE_QUEUE 0x0080
|
||||
#define TUN_PERSIST 0x0100
|
||||
#define TUN_VNET_HDR 0x0200
|
||||
#define TUN_TAP_MQ 0x0400
|
||||
|
||||
/* Ioctl defines */
|
||||
#define TUNSETNOCSUM _IOW('T', 200, int)
|
||||
#define TUNSETDEBUG _IOW('T', 201, int)
|
||||
|
|
@ -58,6 +48,8 @@
|
|||
#define TUNSETQUEUE _IOW('T', 217, int)
|
||||
#define TUNSETIFINDEX _IOW('T', 218, unsigned int)
|
||||
#define TUNGETFILTER _IOR('T', 219, struct sock_fprog)
|
||||
#define TUNSETVNETLE _IOW('T', 220, int)
|
||||
#define TUNGETVNETLE _IOR('T', 221, int)
|
||||
|
||||
/* TUNSETIFF ifr flags */
|
||||
#define IFF_TUN 0x0001
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ enum tunnel_encap_types {
|
|||
|
||||
#define TUNNEL_ENCAP_FLAG_CSUM (1<<0)
|
||||
#define TUNNEL_ENCAP_FLAG_CSUM6 (1<<1)
|
||||
#define TUNNEL_ENCAP_FLAG_REMCSUM (1<<2)
|
||||
|
||||
/* SIT-mode i_flags */
|
||||
#define SIT_ISATAP 0x0001
|
||||
|
|
|
|||
|
|
@ -35,11 +35,11 @@ enum {
|
|||
*/
|
||||
|
||||
#define NTF_USE 0x01
|
||||
#define NTF_PROXY 0x08 /* == ATF_PUBL */
|
||||
#define NTF_ROUTER 0x80
|
||||
|
||||
#define NTF_SELF 0x02
|
||||
#define NTF_MASTER 0x04
|
||||
#define NTF_PROXY 0x08 /* == ATF_PUBL */
|
||||
#define NTF_EXT_LEARNED 0x10
|
||||
#define NTF_ROUTER 0x80
|
||||
|
||||
/*
|
||||
* Neighbor Cache Entry States.
|
||||
|
|
|
|||
|
|
@ -237,7 +237,6 @@ enum {
|
|||
#define RTPROT_MROUTED 17 /* Multicast daemon */
|
||||
#define RTPROT_BABEL 42 /* Babel daemon */
|
||||
|
||||
|
||||
/* rtm_scope
|
||||
|
||||
Really it is not scope, but sort of distance to the destination.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_TC_VLAN_H
|
||||
#define __LINUX_TC_VLAN_H
|
||||
|
||||
#include <linux/pkt_cls.h>
|
||||
|
||||
#define TCA_ACT_VLAN 12
|
||||
|
||||
#define TCA_VLAN_ACT_POP 1
|
||||
#define TCA_VLAN_ACT_PUSH 2
|
||||
|
||||
struct tc_vlan {
|
||||
tc_gen;
|
||||
int v_action;
|
||||
};
|
||||
|
||||
enum {
|
||||
TCA_VLAN_UNSPEC,
|
||||
TCA_VLAN_TM,
|
||||
TCA_VLAN_PARMS,
|
||||
TCA_VLAN_PUSH_VLAN_ID,
|
||||
TCA_VLAN_PUSH_VLAN_PROTOCOL,
|
||||
__TCA_VLAN_MAX,
|
||||
};
|
||||
#define TCA_VLAN_MAX (__TCA_VLAN_MAX - 1)
|
||||
|
||||
#endif
|
||||
|
|
@ -6,7 +6,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
|
|||
iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o link_vti6.o \
|
||||
iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
|
||||
link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \
|
||||
iplink_bridge.o iplink_bridge_slave.o ipfou.o
|
||||
iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o
|
||||
|
||||
RTMONOBJ=rtmon.o
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ void iplink_usage(void)
|
|||
fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n");
|
||||
fprintf(stderr, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n");
|
||||
fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti | nlmon |\n");
|
||||
fprintf(stderr, " bond_slave }\n");
|
||||
fprintf(stderr, " bond_slave | ipvlan }\n");
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
/* iplink_ipvlan.c IPVLAN device support
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Authors: Mahesh Bandewar <maheshb@google.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/if_link.h>
|
||||
|
||||
#include "rt_names.h"
|
||||
#include "utils.h"
|
||||
#include "ip_common.h"
|
||||
|
||||
static void ipvlan_explain(FILE *f)
|
||||
{
|
||||
fprintf(f, "Usage: ... ipvlan [ mode { l2 | l3 } ]\n");
|
||||
}
|
||||
|
||||
static void explain(void)
|
||||
{
|
||||
ipvlan_explain(stderr);
|
||||
}
|
||||
|
||||
static int mode_arg(void)
|
||||
{
|
||||
fprintf(stderr, "Error: argument of \"mode\" must be either \"l2\", "
|
||||
"or \"l3\"\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ipvlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||
struct nlmsghdr *n)
|
||||
{
|
||||
while (argc > 0) {
|
||||
if (matches(*argv, "mode") == 0) {
|
||||
__u16 mode = 0;
|
||||
NEXT_ARG();
|
||||
|
||||
if (strcmp(*argv, "l2") == 0)
|
||||
mode = IPVLAN_MODE_L2;
|
||||
else if (strcmp(*argv, "l3") == 0)
|
||||
mode = IPVLAN_MODE_L3;
|
||||
else
|
||||
return mode_arg();
|
||||
|
||||
addattr16(n, 1024, IFLA_IPVLAN_MODE, mode);
|
||||
} else if (matches(*argv, "help") == 0) {
|
||||
explain();
|
||||
return -1;
|
||||
} else {
|
||||
fprintf(stderr, "ipvlan: unknown option \"%s\"?\n",
|
||||
*argv);
|
||||
explain();
|
||||
return -1;
|
||||
}
|
||||
argc--, argv++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ipvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
||||
{
|
||||
|
||||
if (!tb)
|
||||
return;
|
||||
|
||||
if (tb[IFLA_IPVLAN_MODE]) {
|
||||
if (RTA_PAYLOAD(tb[IFLA_IPVLAN_MODE]) == sizeof(__u16)) {
|
||||
__u16 mode = rta_getattr_u16(tb[IFLA_IPVLAN_MODE]);
|
||||
|
||||
fprintf(f, " mode %s ",
|
||||
mode == IPVLAN_MODE_L2 ? "l2" :
|
||||
mode == IPVLAN_MODE_L3 ? "l3" : "unknown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ipvlan_print_help(struct link_util *lu, int argc, char **argv,
|
||||
FILE *f)
|
||||
{
|
||||
ipvlan_explain(f);
|
||||
}
|
||||
|
||||
struct link_util ipvlan_link_util = {
|
||||
.id = "ipvlan",
|
||||
.maxattr = IFLA_IPVLAN_MAX,
|
||||
.parse_opt = ipvlan_parse_opt,
|
||||
.print_opt = ipvlan_print_opt,
|
||||
.print_help = ipvlan_print_help,
|
||||
};
|
||||
32
ip/iproute.c
32
ip/iproute.c
|
|
@ -80,6 +80,7 @@ static void usage(void)
|
|||
fprintf(stderr, " [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n");
|
||||
fprintf(stderr, " [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n");
|
||||
fprintf(stderr, " [ rto_min TIME ] [ hoplimit NUMBER ] [ initrwnd NUMBER ]\n");
|
||||
fprintf(stderr, " [ features FEATURES ]\n");
|
||||
fprintf(stderr, " [ quickack BOOL ]\n");
|
||||
fprintf(stderr, "TYPE := [ unicast | local | broadcast | multicast | throw |\n");
|
||||
fprintf(stderr, " unreachable | prohibit | blackhole | nat ]\n");
|
||||
|
|
@ -89,6 +90,7 @@ static void usage(void)
|
|||
fprintf(stderr, "RTPROTO := [ kernel | boot | static | NUMBER ]\n");
|
||||
fprintf(stderr, "TIME := NUMBER[s|ms]\n");
|
||||
fprintf(stderr, "BOOL := [1|0]\n");
|
||||
fprintf(stderr, "FEATURES := ecn\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
|
@ -280,6 +282,19 @@ static int calc_host_len(const struct rtmsg *r)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void print_rtax_features(FILE *fp, unsigned int features)
|
||||
{
|
||||
unsigned int of = features;
|
||||
|
||||
if (features & RTAX_FEATURE_ECN) {
|
||||
fprintf(fp, " ecn");
|
||||
features &= ~RTAX_FEATURE_ECN;
|
||||
}
|
||||
|
||||
if (features)
|
||||
fprintf(fp, " 0x%x", of);
|
||||
}
|
||||
|
||||
int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
||||
{
|
||||
FILE *fp = (FILE*)arg;
|
||||
|
|
@ -535,6 +550,9 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
|||
|
||||
val = *(unsigned*)RTA_DATA(mxrta[i]);
|
||||
switch (i) {
|
||||
case RTAX_FEATURES:
|
||||
print_rtax_features(fp, val);
|
||||
break;
|
||||
case RTAX_HOPLIMIT:
|
||||
if ((int)val == -1)
|
||||
val = 0;
|
||||
|
|
@ -885,6 +903,20 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
|
|||
if (get_unsigned(&win, *argv, 0))
|
||||
invarg("\"initrwnd\" value is invalid\n", *argv);
|
||||
rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITRWND, win);
|
||||
} else if (matches(*argv, "features") == 0) {
|
||||
unsigned int features = 0;
|
||||
|
||||
while (argc > 0) {
|
||||
NEXT_ARG();
|
||||
|
||||
if (strcmp(*argv, "ecn") == 0)
|
||||
features |= RTAX_FEATURE_ECN;
|
||||
else
|
||||
invarg("\"features\" value not valid\n", *argv);
|
||||
break;
|
||||
}
|
||||
|
||||
rta_addattr32(mxrta, sizeof(mxbuf), RTAX_FEATURES, features);
|
||||
} else if (matches(*argv, "quickack") == 0) {
|
||||
unsigned quickack;
|
||||
NEXT_ARG();
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@ replace " } "
|
|||
.IR NUMBER " ] [ "
|
||||
.B initrwnd
|
||||
.IR NUMBER " ] [ "
|
||||
.B features
|
||||
.IR FEATURES " ] [ "
|
||||
.B quickack
|
||||
.IR BOOL " ]"
|
||||
|
||||
|
|
@ -140,6 +142,10 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]"
|
|||
.BR kernel " | " boot " | " static " |"
|
||||
.IR NUMBER " ]"
|
||||
|
||||
.ti -8
|
||||
.IR FEATURES " := [ "
|
||||
.BR ecn " | ]"
|
||||
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B ip route
|
||||
|
|
@ -410,6 +416,18 @@ the initial receive window size for connections to this destination.
|
|||
Actual window size is this value multiplied by the MSS of the connection.
|
||||
The default value is zero, meaning to use Slow Start value.
|
||||
|
||||
.TP
|
||||
.BI features " FEATURES " (3.18+ only)
|
||||
Enable or disable per-route features. Only available feature at this
|
||||
time is
|
||||
.B ecn
|
||||
to enable explicit congestion notification when initiating connections to the
|
||||
given destination network.
|
||||
When responding to a connection request from the given network, ecn will
|
||||
also be used even if the
|
||||
.B net.ipv4.tcp_ecn
|
||||
sysctl is set to 0.
|
||||
|
||||
.TP
|
||||
.BI quickack " BOOL " "(3.11+ only)"
|
||||
Enable or disable quick ack for connections to this destination.
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ TCMODULES += m_pedit.o
|
|||
TCMODULES += m_skbedit.o
|
||||
TCMODULES += m_csum.o
|
||||
TCMODULES += m_simple.o
|
||||
TCMODULES += m_vlan.o
|
||||
TCMODULES += p_ip.o
|
||||
TCMODULES += p_icmp.o
|
||||
TCMODULES += p_tcp.o
|
||||
|
|
|
|||
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* m_vlan.c vlan manipulation module
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Authors: Jiri Pirko <jiri@resnulli.us>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include "utils.h"
|
||||
#include "rt_names.h"
|
||||
#include "tc_util.h"
|
||||
#include <linux/tc_act/tc_vlan.h>
|
||||
|
||||
static void explain(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: vlan pop\n");
|
||||
fprintf(stderr, " vlan push [ protocol VLANPROTO ] id VLANID\n");
|
||||
fprintf(stderr, " VLANPROTO is one of 802.1Q or 802.1AD\n");
|
||||
fprintf(stderr, " with default: 802.1Q\n");
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
explain();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static int parse_vlan(struct action_util *a, int *argc_p, char ***argv_p,
|
||||
int tca_id, struct nlmsghdr *n)
|
||||
{
|
||||
int argc = *argc_p;
|
||||
char **argv = *argv_p;
|
||||
struct rtattr *tail;
|
||||
int action = 0;
|
||||
__u16 id;
|
||||
int id_set = 0;
|
||||
__u16 proto;
|
||||
int proto_set = 0;
|
||||
struct tc_vlan parm = { 0 };
|
||||
|
||||
if (matches(*argv, "vlan") != 0)
|
||||
return -1;
|
||||
|
||||
NEXT_ARG();
|
||||
|
||||
while (argc > 0) {
|
||||
if (matches(*argv, "pop") == 0) {
|
||||
if (action) {
|
||||
fprintf(stderr, "unexpected \"%s\" - action already specified\n",
|
||||
*argv);
|
||||
explain();
|
||||
return -1;
|
||||
}
|
||||
action = TCA_VLAN_ACT_POP;
|
||||
} else if (matches(*argv, "push") == 0) {
|
||||
if (action) {
|
||||
fprintf(stderr, "unexpected \"%s\" - action already specified\n",
|
||||
*argv);
|
||||
explain();
|
||||
return -1;
|
||||
}
|
||||
action = TCA_VLAN_ACT_PUSH;
|
||||
} else if (matches(*argv, "id") == 0) {
|
||||
if (action != TCA_VLAN_ACT_PUSH) {
|
||||
fprintf(stderr, "\"%s\" is only valid for push\n",
|
||||
*argv);
|
||||
explain();
|
||||
return -1;
|
||||
}
|
||||
NEXT_ARG();
|
||||
if (get_u16(&id, *argv, 0))
|
||||
invarg("id is invalid", *argv);
|
||||
id_set = 1;
|
||||
} else if (matches(*argv, "protocol") == 0) {
|
||||
if (action != TCA_VLAN_ACT_PUSH) {
|
||||
fprintf(stderr, "\"%s\" is only valid for push\n",
|
||||
*argv);
|
||||
explain();
|
||||
return -1;
|
||||
}
|
||||
NEXT_ARG();
|
||||
if (ll_proto_a2n(&proto, *argv))
|
||||
invarg("protocol is invalid", *argv);
|
||||
proto_set = 1;
|
||||
} else if (matches(*argv, "help") == 0) {
|
||||
usage();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
parm.action = TC_ACT_PIPE;
|
||||
if (argc) {
|
||||
if (matches(*argv, "reclassify") == 0) {
|
||||
parm.action = TC_ACT_RECLASSIFY;
|
||||
NEXT_ARG();
|
||||
} else if (matches(*argv, "pipe") == 0) {
|
||||
parm.action = TC_ACT_PIPE;
|
||||
NEXT_ARG();
|
||||
} else if (matches(*argv, "drop") == 0 ||
|
||||
matches(*argv, "shot") == 0) {
|
||||
parm.action = TC_ACT_SHOT;
|
||||
NEXT_ARG();
|
||||
} else if (matches(*argv, "continue") == 0) {
|
||||
parm.action = TC_ACT_UNSPEC;
|
||||
NEXT_ARG();
|
||||
} else if (matches(*argv, "pass") == 0) {
|
||||
parm.action = TC_ACT_OK;
|
||||
NEXT_ARG();
|
||||
}
|
||||
}
|
||||
|
||||
if (argc) {
|
||||
if (matches(*argv, "index") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u32(&parm.index, *argv, 10)) {
|
||||
fprintf(stderr, "vlan: Illegal \"index\"\n");
|
||||
return -1;
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
}
|
||||
|
||||
if (action == TCA_VLAN_ACT_PUSH && !id_set) {
|
||||
fprintf(stderr, "id needs to be set for push\n");
|
||||
explain();
|
||||
return -1;
|
||||
}
|
||||
|
||||
parm.v_action = action;
|
||||
tail = NLMSG_TAIL(n);
|
||||
addattr_l(n, MAX_MSG, tca_id, NULL, 0);
|
||||
addattr_l(n, MAX_MSG, TCA_VLAN_PARMS, &parm, sizeof(parm));
|
||||
if (id_set)
|
||||
addattr_l(n, MAX_MSG, TCA_VLAN_PUSH_VLAN_ID, &id, 2);
|
||||
if (proto_set) {
|
||||
if (proto != htons(ETH_P_8021Q) &&
|
||||
proto != htons(ETH_P_8021AD)) {
|
||||
fprintf(stderr, "protocol not supported\n");
|
||||
explain();
|
||||
return -1;
|
||||
}
|
||||
|
||||
addattr_l(n, MAX_MSG, TCA_VLAN_PUSH_VLAN_PROTOCOL, &proto, 2);
|
||||
}
|
||||
tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
|
||||
|
||||
*argc_p = argc;
|
||||
*argv_p = argv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_vlan(struct action_util *au, FILE *f, struct rtattr *arg)
|
||||
{
|
||||
SPRINT_BUF(b1);
|
||||
struct rtattr *tb[TCA_VLAN_MAX + 1];
|
||||
__u16 val;
|
||||
struct tc_vlan *parm;
|
||||
|
||||
if (arg == NULL)
|
||||
return -1;
|
||||
|
||||
parse_rtattr_nested(tb, TCA_VLAN_MAX, arg);
|
||||
|
||||
if (!tb[TCA_VLAN_PARMS]) {
|
||||
fprintf(f, "[NULL vlan parameters]");
|
||||
return -1;
|
||||
}
|
||||
parm = RTA_DATA(tb[TCA_VLAN_PARMS]);
|
||||
|
||||
fprintf(f, " vlan");
|
||||
|
||||
switch(parm->v_action) {
|
||||
case TCA_VLAN_ACT_POP:
|
||||
fprintf(f, " pop");
|
||||
break;
|
||||
case TCA_VLAN_ACT_PUSH:
|
||||
fprintf(f, " push");
|
||||
if (tb[TCA_VLAN_PUSH_VLAN_ID]) {
|
||||
val = rta_getattr_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
|
||||
fprintf(f, " id %u", val);
|
||||
}
|
||||
if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) {
|
||||
fprintf(f, " protocol %s",
|
||||
ll_proto_n2a(rta_getattr_u16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]),
|
||||
b1, sizeof(b1)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(f, "\n\t index %d ref %d bind %d", parm->index, parm->refcnt,
|
||||
parm->bindcnt);
|
||||
|
||||
if (show_stats) {
|
||||
if (tb[TCA_VLAN_TM]) {
|
||||
struct tcf_t *tm = RTA_DATA(tb[TCA_VLAN_TM]);
|
||||
print_tm(f, tm);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(f, "\n ");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct action_util vlan_action_util = {
|
||||
.id = "vlan",
|
||||
.parse_aopt = parse_vlan,
|
||||
.print_aopt = print_vlan,
|
||||
};
|
||||
Loading…
Reference in New Issue