mirror of
https://git.proxmox.com/git/mirror_iproute2
synced 2025-10-18 22:02:00 +00:00
ip link: Add support to configure SR-IOV VF to vlan protocol 802.1ad (VST QinQ)
Introduce a new API that exposes a list of vlans per VF (IFLA_VF_VLAN_LIST), giving the ability for user-space application to specify it for the VF as an option to support 802.1ad (VST QinQ). We introduce struct vf_vlan_info, which extends struct vf_vlan and adds an optional VF VLAN proto parameter. Default VLAN-protocol is 802.1Q. Add IFLA_VF_VLAN_LIST in addition to IFLA_VF_VLAN to keep backward compatibility with older kernel versions. Suitable ip link tool command examples: - Set vf vlan protocol 802.1ad (S-TAG) ip link set eth0 vf 1 vlan 100 proto 802.1ad - Set vf vlan S-TAG and vlan C-TAG (VST QinQ) ip link set eth0 vf 1 vlan 100 proto 802.1ad vlan 30 proto 802.1Q - Set vf to VST (802.1Q) mode ip link set eth0 vf 1 vlan 100 proto 802.1Q - Or by omitting the new parameter (backward compatible) ip link set eth0 vf 1 vlan 100 Signed-off-by: Moshe Shemesh <moshe@mellanox.com> Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
This commit is contained in:
parent
39f8caeb96
commit
56e9f0ab19
@ -321,7 +321,6 @@ static void print_vf_stats64(FILE *fp, struct rtattr *vfstats);
|
||||
static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
|
||||
{
|
||||
struct ifla_vf_mac *vf_mac;
|
||||
struct ifla_vf_vlan *vf_vlan;
|
||||
struct ifla_vf_tx_rate *vf_tx_rate;
|
||||
struct ifla_vf_spoofchk *vf_spoofchk;
|
||||
struct ifla_vf_link_state *vf_linkstate;
|
||||
@ -338,7 +337,6 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
|
||||
parse_rtattr_nested(vf, IFLA_VF_MAX, vfinfo);
|
||||
|
||||
vf_mac = RTA_DATA(vf[IFLA_VF_MAC]);
|
||||
vf_vlan = RTA_DATA(vf[IFLA_VF_VLAN]);
|
||||
vf_tx_rate = RTA_DATA(vf[IFLA_VF_TX_RATE]);
|
||||
|
||||
/* Check if the spoof checking vf info type is supported by
|
||||
@ -369,10 +367,35 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
|
||||
fprintf(fp, "%s vf %d MAC %s", _SL_, vf_mac->vf,
|
||||
ll_addr_n2a((unsigned char *)&vf_mac->mac,
|
||||
ETH_ALEN, 0, b1, sizeof(b1)));
|
||||
if (vf_vlan->vlan)
|
||||
fprintf(fp, ", vlan %d", vf_vlan->vlan);
|
||||
if (vf_vlan->qos)
|
||||
fprintf(fp, ", qos %d", vf_vlan->qos);
|
||||
if (vf[IFLA_VF_VLAN_LIST]) {
|
||||
struct rtattr *i, *vfvlanlist = vf[IFLA_VF_VLAN_LIST];
|
||||
int rem = RTA_PAYLOAD(vfvlanlist);
|
||||
|
||||
for (i = RTA_DATA(vfvlanlist);
|
||||
RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
|
||||
struct ifla_vf_vlan_info *vf_vlan_info =
|
||||
RTA_DATA(i);
|
||||
SPRINT_BUF(b2);
|
||||
|
||||
if (vf_vlan_info->vlan)
|
||||
fprintf(fp, ", vlan %d", vf_vlan_info->vlan);
|
||||
if (vf_vlan_info->qos)
|
||||
fprintf(fp, ", qos %d", vf_vlan_info->qos);
|
||||
if (vf_vlan_info->vlan_proto &&
|
||||
vf_vlan_info->vlan_proto != htons(ETH_P_8021Q))
|
||||
fprintf(fp, ", vlan protocol %s",
|
||||
ll_proto_n2a(vf_vlan_info->vlan_proto,
|
||||
b2, sizeof(b2)));
|
||||
|
||||
}
|
||||
} else {
|
||||
struct ifla_vf_vlan *vf_vlan = RTA_DATA(vf[IFLA_VF_VLAN]);
|
||||
|
||||
if (vf_vlan->vlan)
|
||||
fprintf(fp, ", vlan %d", vf_vlan->vlan);
|
||||
if (vf_vlan->qos)
|
||||
fprintf(fp, ", qos %d", vf_vlan->qos);
|
||||
}
|
||||
if (vf_tx_rate->rate)
|
||||
fprintf(fp, ", tx rate %d (Mbps)", vf_tx_rate->rate);
|
||||
|
||||
|
102
ip/iplink.c
102
ip/iplink.c
@ -76,7 +76,7 @@ void iplink_usage(void)
|
||||
fprintf(stderr, " [ link-netnsid ID ]\n");
|
||||
fprintf(stderr, " [ alias NAME ]\n");
|
||||
fprintf(stderr, " [ vf NUM [ mac LLADDR ]\n");
|
||||
fprintf(stderr, " [ vlan VLANID [ qos VLAN-QOS ] ]\n");
|
||||
fprintf(stderr, " [ vlan VLANID [ qos VLAN-QOS ] [ proto VLAN-PROTO ] ]\n");
|
||||
|
||||
fprintf(stderr, " [ rate TXRATE ]\n");
|
||||
fprintf(stderr, " [ max_tx_rate TXRATE ]\n");
|
||||
@ -255,6 +255,60 @@ static int nl_get_ll_addr_len(unsigned int dev_index)
|
||||
return RTA_PAYLOAD(tb[IFLA_ADDRESS]);
|
||||
}
|
||||
|
||||
static void iplink_parse_vf_vlan_info(int vf, int *argcp, char ***argvp,
|
||||
struct ifla_vf_vlan_info *ivvip)
|
||||
{
|
||||
int argc = *argcp;
|
||||
char **argv = *argvp;
|
||||
|
||||
NEXT_ARG();
|
||||
if (get_unsigned(&ivvip->vlan, *argv, 0))
|
||||
invarg("Invalid \"vlan\" value\n", *argv);
|
||||
|
||||
ivvip->vf = vf;
|
||||
ivvip->qos = 0;
|
||||
ivvip->vlan_proto = htons(ETH_P_8021Q);
|
||||
if (NEXT_ARG_OK()) {
|
||||
NEXT_ARG();
|
||||
if (matches(*argv, "qos") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_unsigned(&ivvip->qos, *argv, 0))
|
||||
invarg("Invalid \"qos\" value\n", *argv);
|
||||
} else {
|
||||
/* rewind arg */
|
||||
PREV_ARG();
|
||||
}
|
||||
}
|
||||
if (NEXT_ARG_OK()) {
|
||||
NEXT_ARG();
|
||||
if (matches(*argv, "proto") == 0) {
|
||||
NEXT_ARG();
|
||||
if (ll_proto_a2n(&ivvip->vlan_proto, *argv))
|
||||
invarg("protocol is invalid\n", *argv);
|
||||
if (ivvip->vlan_proto != htons(ETH_P_8021AD) &&
|
||||
ivvip->vlan_proto != htons(ETH_P_8021Q)) {
|
||||
SPRINT_BUF(b1);
|
||||
SPRINT_BUF(b2);
|
||||
char msg[64 + sizeof(b1) + sizeof(b2)];
|
||||
|
||||
sprintf(msg, "Invalid \"vlan protocol\""
|
||||
" value - supported %s, %s\n",
|
||||
ll_proto_n2a(htons(ETH_P_8021Q),
|
||||
b1, sizeof(b1)),
|
||||
ll_proto_n2a(htons(ETH_P_8021AD),
|
||||
b2, sizeof(b2)));
|
||||
invarg(msg, *argv);
|
||||
}
|
||||
} else {
|
||||
/* rewind arg */
|
||||
PREV_ARG();
|
||||
}
|
||||
}
|
||||
|
||||
*argcp = argc;
|
||||
*argvp = argv;
|
||||
}
|
||||
|
||||
static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
|
||||
struct iplink_req *req, int dev_index)
|
||||
{
|
||||
@ -308,27 +362,41 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
|
||||
addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC,
|
||||
&ivm, sizeof(ivm));
|
||||
} else if (matches(*argv, "vlan") == 0) {
|
||||
struct ifla_vf_vlan ivv;
|
||||
struct ifla_vf_vlan_info ivvi;
|
||||
|
||||
NEXT_ARG();
|
||||
if (get_unsigned(&ivv.vlan, *argv, 0))
|
||||
invarg("Invalid \"vlan\" value\n", *argv);
|
||||
iplink_parse_vf_vlan_info(vf, &argc, &argv, &ivvi);
|
||||
/* support the old interface in case of older kernel*/
|
||||
if (ivvi.vlan_proto == htons(ETH_P_8021Q)) {
|
||||
struct ifla_vf_vlan ivv;
|
||||
|
||||
ivv.vf = vf;
|
||||
ivv.qos = 0;
|
||||
if (NEXT_ARG_OK()) {
|
||||
NEXT_ARG();
|
||||
if (matches(*argv, "qos") == 0) {
|
||||
ivv.vf = ivvi.vf;
|
||||
ivv.vlan = ivvi.vlan;
|
||||
ivv.qos = ivvi.qos;
|
||||
addattr_l(&req->n, sizeof(*req),
|
||||
IFLA_VF_VLAN, &ivv, sizeof(ivv));
|
||||
} else {
|
||||
struct rtattr *vfvlanlist;
|
||||
|
||||
vfvlanlist = addattr_nest(&req->n, sizeof(*req),
|
||||
IFLA_VF_VLAN_LIST);
|
||||
addattr_l(&req->n, sizeof(*req),
|
||||
IFLA_VF_VLAN_INFO, &ivvi,
|
||||
sizeof(ivvi));
|
||||
|
||||
while (NEXT_ARG_OK()) {
|
||||
NEXT_ARG();
|
||||
if (get_unsigned(&ivv.qos, *argv, 0))
|
||||
invarg("Invalid \"qos\" value\n", *argv);
|
||||
} else {
|
||||
/* rewind arg */
|
||||
PREV_ARG();
|
||||
if (matches(*argv, "vlan") != 0) {
|
||||
PREV_ARG();
|
||||
break;
|
||||
}
|
||||
iplink_parse_vf_vlan_info(vf, &argc,
|
||||
&argv, &ivvi);
|
||||
addattr_l(&req->n, sizeof(*req),
|
||||
IFLA_VF_VLAN_INFO, &ivvi,
|
||||
sizeof(ivvi));
|
||||
}
|
||||
addattr_nest_end(&req->n, vfvlanlist);
|
||||
}
|
||||
addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN,
|
||||
&ivv, sizeof(ivv));
|
||||
} else if (matches(*argv, "rate") == 0) {
|
||||
struct ifla_vf_tx_rate ivt;
|
||||
|
||||
|
@ -102,10 +102,7 @@ ip-link \- network device configuration
|
||||
.IR LLADDR " ]"
|
||||
.br
|
||||
.in +9
|
||||
.RB "[ " vlan
|
||||
.IR VLANID " [ "
|
||||
.B qos
|
||||
.IR VLAN-QOS " ] ]"
|
||||
.RI "[ " VFVLAN-LIST " ]"
|
||||
.br
|
||||
.RB "[ " rate
|
||||
.IR TXRATE " ]"
|
||||
@ -191,6 +188,18 @@ ip-link \- network device configuration
|
||||
.IR ETYPE " := [ " TYPE " |"
|
||||
.BR bridge_slave " | " bond_slave " ]"
|
||||
|
||||
.ti -8
|
||||
.IR VFVLAN-LIST " := [ " VFVLAN-LIST " ] " VFVLAN
|
||||
|
||||
.ti -8
|
||||
.IR VFVLAN " := "
|
||||
.RB "[ " vlan
|
||||
.IR VLANID " [ "
|
||||
.B qos
|
||||
.IR VLAN-QOS " ] ["
|
||||
.B proto
|
||||
.IR VLAN-PROTO " ] ]"
|
||||
|
||||
.SH "DESCRIPTION"
|
||||
.SS ip link add - add virtual link
|
||||
|
||||
@ -1237,6 +1246,19 @@ and
|
||||
.B qos
|
||||
as 0 disables VLAN tagging and filtering for the VF.
|
||||
|
||||
.sp
|
||||
.BI proto " VLAN-PROTO"
|
||||
- assign VLAN PROTOCOL for the VLAN tag, either 802.1Q or 802.1ad.
|
||||
Setting to 802.1ad, all traffic sent from the VF will be tagged with VLAN S-Tag.
|
||||
Incoming traffic will have VLAN S-Tags stripped before being passed to the VF.
|
||||
Setting to 802.1ad also enables an option to concatenate another VLAN tag, so both
|
||||
S-TAG and C-TAG will be inserted/stripped for outgoing/incoming traffic, respectively.
|
||||
If not specified, the value is assumed to be 802.1Q. Both the
|
||||
.B vf
|
||||
and
|
||||
.B vlan
|
||||
parameters must be specified.
|
||||
|
||||
.sp
|
||||
.BI rate " TXRATE"
|
||||
-- change the allowed transmit bandwidth, in Mbps, for the specified VF.
|
||||
|
Loading…
Reference in New Issue
Block a user