[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1572463033-26368-4-git-send-email-lariel@mellanox.com>
Date: Wed, 30 Oct 2019 19:17:32 +0000
From: Ariel Levkovich <lariel@...lanox.com>
To: "netdev@...r.kernel.org" <netdev@...r.kernel.org>
CC: Jiri Pirko <jiri@...lanox.com>,
Ariel Levkovich <lariel@...lanox.com>
Subject: [PATCH 3/3] ip: Add SR-IOV VF VGT+ support
Introduce a new API that can add/remove allowed vlan-ids per VF to
support the VGT+ feature.
Also intoroduce a new API to query the current allowed vlan-ids per VF.
VGT+ is a security feature that gives the administrator the ability of
controlling the allowed vlan-ids list that can be transmitted/received
from/to the VF.
The allowed vlan-ids list is called "trunk".
Admin can add/delete a range of allowed vlan-ids via iptool.
Example:
After this series of configuration :
1) ip link set eth3 vf 0 trunk add 10 100 (allow vlan-id 10-100, default tpid 0x8100)
2) ip link set eth3 vf 0 trunk add 105 proto 802.1q (allow vlan-id 105 tpid 0x8100)
3) ip link set eth3 vf 0 trunk add 105 proto 802.1ad (allow vlan-id 105 tpid 0x88a8)
4) ip link set eth3 vf 0 trunk rem 90 (block vlan-id 90)
5) ip link set eth3 vf 0 trunk rem 50 60 (block vlan-ids 50-60)
The VF 0 can only communicate on vlan-ids: 10-49,61-89,91-100,105 with tpid 0x8100
and vlan-id 105 with tpid 0x88a8.
For this purpose we added the following netlink sr-iov commands:
1) IFLA_VF_VLAN_RANGE: used to add/remove allowed vlan-ids range.
we added the ifla_vf_vlan_range struct to specify the range we want to
add/remove from the userspace.
2) IFLA_VF_VLAN_TRUNK: used to query the allowed vlan-ids trunk.
we added ifla_vf_vlan_trunk struct for sending the allowed vlan-ids
trunk to the userspace.
The allowed vlan-ids will be presented only when the query is for
a specific vf.
Example:
Running the following command will set the vlan trunk to include 10-100:
1)ip link set eth3 vf 0 trunk add 10 100
Then running:
2)ip link show dev eth3 vf 0
Will show:
vf 0 link/ether 00:00:00:00:00:00 brd 00:00:00:00:00:f3, spoof checking off, link-state auto, trust off, query_rss off
Allowed 802.1Q VLANs: 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100.
Signed-off-by: Ariel Levkovich <lariel@...lanox.com>
---
include/uapi/linux/if_link.h | 19 ++++++++++++++++
ip/ipaddress.c | 52 ++++++++++++++++++++++++++++++++++++++++++++
ip/iplink.c | 46 +++++++++++++++++++++++++++++++++++++++
man/man8/ip-link.8.in | 17 ++++++++++++++-
4 files changed, 133 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 6304add..ff29803 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -698,6 +698,8 @@ enum {
IFLA_VF_VLAN_LIST, /* nested list of vlans, option for QinQ */
IFLA_VF_BROADCAST, /* VF broadcast */
IFLA_VF_VLAN_MODE, /* vlan tagging mode */
+ IFLA_VF_VLAN_RANGE, /* VF add/remove vlan-ids range */
+ IFLA_VF_VLAN_TRUNK, /* VF allowed vlan-ids trunk */
__IFLA_VF_MAX,
};
@@ -747,6 +749,23 @@ struct ifla_vf_vlan_info {
__be16 vlan_proto; /* VLAN protocol either 802.1Q or 802.1ad */
};
+struct ifla_vf_vlan_range {
+ __u32 vf;
+ __u32 start_vid; /* 0 - 4095, 0 - for untagged and priority tagged */
+ __u32 end_vid; /* 0 - 4095, 0 - for untagged and priority tagged */
+ __u32 setting; /* 0 : Add range , 1 : Remove range */
+ __be16 vlan_proto; /* VLAN protocol either 802.1Q or 802.1ad */
+};
+
+#define BITS_PER_BYTE 8
+#define VLAN_N_VID 4096
+#define VF_VLAN_BITMAP __KERNEL_DIV_ROUND_UP(VLAN_N_VID, sizeof(__u64) * BITS_PER_BYTE)
+struct ifla_vf_vlan_trunk {
+ __u32 vf;
+ __u64 trunk_vid_8021q_bitmap[VF_VLAN_BITMAP];
+ __u64 trunk_vid_8021ad_bitmap[VF_VLAN_BITMAP];
+};
+
struct ifla_vf_tx_rate {
__u32 vf;
__u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index a66ca02..90efbff 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -350,6 +350,7 @@ static void print_af_spec(FILE *fp, struct rtattr *af_spec_attr)
}
static void print_vf_stats64(FILE *fp, struct rtattr *vfstats);
+static void print_vf_vlan_trunk(FILE *fp, __u64 *bitmap, const char *proto);
static void print_vfinfo(FILE *fp, struct ifinfomsg *ifi, struct rtattr *vfinfo)
{
@@ -548,6 +549,18 @@ static void print_vfinfo(FILE *fp, struct ifinfomsg *ifi, struct rtattr *vfinfo)
if (vf[IFLA_VF_STATS] && show_stats)
print_vf_stats64(fp, vf[IFLA_VF_STATS]);
+
+ /*
+ * VF trunk query should always be the last if-condition because it adds
+ * new lines to the end of the vf info output.
+ */
+ if (vf[IFLA_VF_VLAN_TRUNK]) {
+ struct ifla_vf_vlan_trunk *vf_trunk =
+ RTA_DATA(vf[IFLA_VF_VLAN_TRUNK]);
+
+ print_vf_vlan_trunk(fp, vf_trunk->trunk_vid_8021q_bitmap, "802.1Q");
+ print_vf_vlan_trunk(fp, vf_trunk->trunk_vid_8021ad_bitmap, "802.1ad");
+ }
}
void print_num(FILE *fp, unsigned int width, uint64_t count)
@@ -590,6 +603,45 @@ void print_num(FILE *fp, unsigned int width, uint64_t count)
fprintf(fp, "%-*s ", width, buf);
}
+static void print_vf_vlan_trunk(FILE *fp, __u64 *bitmap, const char *proto)
+{
+#define VF_VLAN_TRUNK_LINE_SZ 100
+ int vids_per_dword = sizeof(bitmap[0]) * 8;
+ char trunk_line[2 * VF_VLAN_TRUNK_LINE_SZ] = {0};
+ bool printed_title = false;
+ bool need_newline = false;
+ int vid;
+
+ for (vid = 0; vid < VLAN_N_VID ; vid++) {
+ if ((bitmap[vid / vids_per_dword] >> (vid % vids_per_dword)) & 0x1) {
+ if (strlen(trunk_line) >= VF_VLAN_TRUNK_LINE_SZ)
+ need_newline = true;
+
+ if (!printed_title) {
+ sprintf(trunk_line,
+ "\n Allowed %s VLANs: ", proto);
+ printed_title = true;
+ }
+
+ if (need_newline) {
+ fprintf(fp, "%s", trunk_line);
+ trunk_line[0] = '\0';
+ }
+
+ sprintf(trunk_line, "%s%s%d, ", trunk_line,
+ (need_newline ? "\n " : ""), vid);
+
+ need_newline = false;
+ }
+ }
+
+ if (strlen(trunk_line)) {
+ trunk_line[strlen(trunk_line) - 2] = '.';
+ trunk_line[strlen(trunk_line) - 1] = '\0';
+ fprintf(fp, "%s", trunk_line);
+ }
+}
+
static void print_vf_stats64(FILE *fp, struct rtattr *vfstats)
{
struct rtattr *vf[IFLA_VF_STATS_MAX + 1];
diff --git a/ip/iplink.c b/ip/iplink.c
index ef33232..31076fc 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -89,6 +89,7 @@ void iplink_usage(void)
" [ alias NAME ]\n"
" [ vf NUM [ mac LLADDR ]\n"
" [ vlan VLANID [ qos VLAN-QOS ] [ proto VLAN-PROTO ] ]\n"
+ " [ trunk { add | rem } START-VLANID [ END-VLANID ] [ proto VLAN-PROTO ] ]\n"
" [ rate TXRATE ]\n"
" [ max_tx_rate TXRATE ]\n"
" [ min_tx_rate TXRATE ]\n"
@@ -429,6 +430,51 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
}
addattr_nest_end(&req->n, vfvlanlist);
}
+ } else if (matches(*argv, "trunk") == 0) {
+ struct ifla_vf_vlan_range ivvr;
+
+ ivvr.vf = vf;
+ ivvr.vlan_proto = htons(ETH_P_8021Q);
+ NEXT_ARG();
+ if (matches(*argv, "add") && matches(*argv, "rem"))
+ invarg("Invalid \"trunk\" operation\n", *argv);
+ ivvr.setting = !matches(*argv, "add");
+ NEXT_ARG();
+ if (get_unsigned(&ivvr.start_vid, *argv, 0))
+ invarg("Invalid \"trunk\" start value\n", *argv);
+ ivvr.end_vid = ivvr.start_vid;
+ if (NEXT_ARG_OK()) {
+ NEXT_ARG();
+ if (get_unsigned(&ivvr.end_vid, *argv, 0))
+ PREV_ARG();
+ }
+ if (NEXT_ARG_OK()) {
+ NEXT_ARG();
+ if (matches(*argv, "proto") == 0) {
+ NEXT_ARG();
+ if (ll_proto_a2n(&ivvr.vlan_proto, *argv))
+ invarg("protocol is invalid\n", *argv);
+ if (ivvr.vlan_proto != htons(ETH_P_8021AD) &&
+ ivvr.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();
+ }
+ }
+ addattr_l(&req->n, sizeof(*req),
+ IFLA_VF_VLAN_RANGE, &ivvr, sizeof(ivvr));
} else if (matches(*argv, "rate") == 0) {
struct ifla_vf_tx_rate ivt;
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
index 29744d4..23f6235 100644
--- a/man/man8/ip-link.8.in
+++ b/man/man8/ip-link.8.in
@@ -128,7 +128,12 @@ ip-link \- network device configuration
.br
.RB "[ " node_guid " eui64 ]"
.br
-.RB "[ " port_guid " eui64 ] ]"
+.RB "[ " port_guid " eui64 ]"
+.br
+.RB "[ " trunk " { " add " | " rem " } "
+.IR START-VLAN-ID " [ " END-VLAN-ID " ] "
+.RB "[ " proto
+.IR VLAN-PROTO " ] ] ] "
.br
.in -9
.RB "[ { " xdp " | " xdpgeneric " | " xdpdrv " | " xdpoffload " } { " off " | "
@@ -2043,6 +2048,16 @@ performance. (e.g. VF multicast promiscuous mode)
.sp
.BI port_guid " eui64"
- configure port GUID for Infiniband VFs.
+.sp
+.BI trunk " add|rem START-VLANID [END-VLANID] [proto VLAN-PROTO] "
+- add or remove allowed vlan-ids range that can be used by the VF. Range 0-4095
+while 0 is used for untagged and priority tagged traffic.
+.B vf
+parameter must be specified.
+.B END-VLANID
+parameter is optional. If omitted, assumes range of one vlan-id.
+.B proto
+parameter is optional, either 802.1Q or 802.1ad. If omitted, assumes 802.1Q.
.in -8
.TP
--
1.8.3.1
Powered by blists - more mailing lists