|
|
99be8f |
From dfbec1b67fc02a5af0d5cc30328b918902f20717 Mon Sep 17 00:00:00 2001
|
|
|
99be8f |
From: Andrea Claudi <aclaudi@redhat.com>
|
|
|
99be8f |
Date: Mon, 25 Mar 2019 12:19:05 +0100
|
|
|
99be8f |
Subject: [PATCH] tc: flower: Add support for QinQ
|
|
|
99be8f |
|
|
|
99be8f |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1642347
|
|
|
99be8f |
Upstream Status: iproute2.git commit 1f0a5dfd388cd
|
|
|
99be8f |
Conflicts: context change due to missing commits
|
|
|
99be8f |
7638ee13c1586 ("tc: flower: support for matching MPLS labels")
|
|
|
99be8f |
e28b88a464c49 ("tc: jsonify flower filter")
|
|
|
99be8f |
also adjust code to use fprintf instead of print_string due to
|
|
|
99be8f |
missing commit d0e720111aad2 ("ip: ipaddress.c: add support for json output")
|
|
|
99be8f |
|
|
|
99be8f |
commit 1f0a5dfd388cd5c25f6a24247667e04b2346e568
|
|
|
99be8f |
Author: Jianbo Liu <jianbol@mellanox.com>
|
|
|
99be8f |
Date: Sat Jun 30 10:01:33 2018 +0000
|
|
|
99be8f |
|
|
|
99be8f |
tc: flower: Add support for QinQ
|
|
|
99be8f |
|
|
|
99be8f |
To support matching on both outer and inner vlan headers,
|
|
|
99be8f |
we add new cvlan_id/cvlan_prio/cvlan_ethtype for inner vlan header.
|
|
|
99be8f |
|
|
|
99be8f |
Example:
|
|
|
99be8f |
# tc filter add dev eth0 protocol 802.1ad parent ffff: \
|
|
|
99be8f |
flower vlan_id 1000 vlan_ethtype 802.1q \
|
|
|
99be8f |
cvlan_id 100 cvlan_ethtype ipv4 \
|
|
|
99be8f |
action vlan pop \
|
|
|
99be8f |
action vlan pop \
|
|
|
99be8f |
action mirred egress redirect dev eth1
|
|
|
99be8f |
|
|
|
99be8f |
# tc filter show dev eth0 ingress
|
|
|
99be8f |
filter protocol 802.1ad pref 1 flower chain 0
|
|
|
99be8f |
filter protocol 802.1ad pref 1 flower chain 0 handle 0x1
|
|
|
99be8f |
vlan_id 1000
|
|
|
99be8f |
vlan_ethtype 802.1Q
|
|
|
99be8f |
cvlan_id 100
|
|
|
99be8f |
cvlan_ethtype ip
|
|
|
99be8f |
eth_type ipv4
|
|
|
99be8f |
in_hw
|
|
|
99be8f |
|
|
|
99be8f |
Signed-off-by: Jianbo Liu <jianbol@mellanox.com>
|
|
|
99be8f |
Acked-by: Jiri Pirko <jiri@mellanox.com>
|
|
|
99be8f |
Signed-off-by: David Ahern <dsahern@gmail.com>
|
|
|
99be8f |
---
|
|
|
99be8f |
man/man8/tc-flower.8 | 23 ++++++++++
|
|
|
99be8f |
tc/f_flower.c | 99 ++++++++++++++++++++++++++++++++++++++------
|
|
|
99be8f |
2 files changed, 110 insertions(+), 12 deletions(-)
|
|
|
99be8f |
|
|
|
99be8f |
diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8
|
|
|
99be8f |
index af19708d9649e..387f73f5cd2e9 100644
|
|
|
99be8f |
--- a/man/man8/tc-flower.8
|
|
|
99be8f |
+++ b/man/man8/tc-flower.8
|
|
|
99be8f |
@@ -29,6 +29,12 @@ flower \- flow based traffic control filter
|
|
|
99be8f |
.IR PRIORITY " | "
|
|
|
99be8f |
.BR vlan_ethtype " { " ipv4 " | " ipv6 " | "
|
|
|
99be8f |
.IR ETH_TYPE " } | "
|
|
|
99be8f |
+.B cvlan_id
|
|
|
99be8f |
+.IR VID " | "
|
|
|
99be8f |
+.B cvlan_prio
|
|
|
99be8f |
+.IR PRIORITY " | "
|
|
|
99be8f |
+.BR cvlan_ethtype " { " ipv4 " | " ipv6 " | "
|
|
|
99be8f |
+.IR ETH_TYPE " } | "
|
|
|
99be8f |
.BR ip_proto " { " tcp " | " udp " | " sctp " | " icmp " | " icmpv6 " | "
|
|
|
99be8f |
.IR IP_PROTO " } | "
|
|
|
99be8f |
.B ip_tos
|
|
|
99be8f |
@@ -121,6 +127,23 @@ Match on layer three protocol.
|
|
|
99be8f |
.I VLAN_ETH_TYPE
|
|
|
99be8f |
may be either
|
|
|
99be8f |
.BR ipv4 ", " ipv6
|
|
|
99be8f |
+or an unsigned 16bit value in hexadecimal format. To match on QinQ packet, it must be 802.1Q or 802.1AD.
|
|
|
99be8f |
+.TP
|
|
|
99be8f |
+.BI cvlan_id " VID"
|
|
|
99be8f |
+Match on QinQ inner vlan tag id.
|
|
|
99be8f |
+.I VID
|
|
|
99be8f |
+is an unsigned 12bit value in decimal format.
|
|
|
99be8f |
+.TP
|
|
|
99be8f |
+.BI cvlan_prio " PRIORITY"
|
|
|
99be8f |
+Match on QinQ inner vlan tag priority.
|
|
|
99be8f |
+.I PRIORITY
|
|
|
99be8f |
+is an unsigned 3bit value in decimal format.
|
|
|
99be8f |
+.TP
|
|
|
99be8f |
+.BI cvlan_ethtype " VLAN_ETH_TYPE"
|
|
|
99be8f |
+Match on QinQ layer three protocol.
|
|
|
99be8f |
+.I VLAN_ETH_TYPE
|
|
|
99be8f |
+may be either
|
|
|
99be8f |
+.BR ipv4 ", " ipv6
|
|
|
99be8f |
or an unsigned 16bit value in hexadecimal format.
|
|
|
99be8f |
.TP
|
|
|
99be8f |
.BI ip_proto " IP_PROTO"
|
|
|
99be8f |
diff --git a/tc/f_flower.c b/tc/f_flower.c
|
|
|
99be8f |
index 5f5236ca523f8..40dcfbd687a20 100644
|
|
|
99be8f |
--- a/tc/f_flower.c
|
|
|
99be8f |
+++ b/tc/f_flower.c
|
|
|
99be8f |
@@ -50,6 +50,9 @@ static void explain(void)
|
|
|
99be8f |
" vlan_id VID |\n"
|
|
|
99be8f |
" vlan_prio PRIORITY |\n"
|
|
|
99be8f |
" vlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n"
|
|
|
99be8f |
+ " cvlan_id VID |\n"
|
|
|
99be8f |
+ " cvlan_prio PRIORITY |\n"
|
|
|
99be8f |
+ " cvlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n"
|
|
|
99be8f |
" dst_mac MASKED-LLADDR |\n"
|
|
|
99be8f |
" src_mac MASKED-LLADDR |\n"
|
|
|
99be8f |
" ip_proto [tcp | udp | sctp | icmp | icmpv6 | IP-PROTO ] |\n"
|
|
|
99be8f |
@@ -126,15 +129,21 @@ err:
|
|
|
99be8f |
return err;
|
|
|
99be8f |
}
|
|
|
99be8f |
|
|
|
99be8f |
+static bool eth_type_vlan(__be16 ethertype)
|
|
|
99be8f |
+{
|
|
|
99be8f |
+ return ethertype == htons(ETH_P_8021Q) ||
|
|
|
99be8f |
+ ethertype == htons(ETH_P_8021AD);
|
|
|
99be8f |
+}
|
|
|
99be8f |
+
|
|
|
99be8f |
static int flower_parse_vlan_eth_type(char *str, __be16 eth_type, int type,
|
|
|
99be8f |
__be16 *p_vlan_eth_type,
|
|
|
99be8f |
struct nlmsghdr *n)
|
|
|
99be8f |
{
|
|
|
99be8f |
__be16 vlan_eth_type;
|
|
|
99be8f |
|
|
|
99be8f |
- if (eth_type != htons(ETH_P_8021Q)) {
|
|
|
99be8f |
- fprintf(stderr,
|
|
|
99be8f |
- "Can't set \"vlan_ethtype\" if ethertype isn't 802.1Q\n");
|
|
|
99be8f |
+ if (!eth_type_vlan(eth_type)) {
|
|
|
99be8f |
+ fprintf(stderr, "Can't set \"%s\" if ethertype isn't 802.1Q or 802.1AD\n",
|
|
|
99be8f |
+ type == TCA_FLOWER_KEY_VLAN_ETH_TYPE ? "vlan_ethtype" : "cvlan_ethtype");
|
|
|
99be8f |
return -1;
|
|
|
99be8f |
}
|
|
|
99be8f |
|
|
|
99be8f |
@@ -583,6 +592,7 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
|
|
|
99be8f |
struct rtattr *tail;
|
|
|
99be8f |
__be16 eth_type = TC_H_MIN(t->tcm_info);
|
|
|
99be8f |
__be16 vlan_ethtype = 0;
|
|
|
99be8f |
+ __be16 cvlan_ethtype = 0;
|
|
|
99be8f |
__u8 ip_proto = 0xff;
|
|
|
99be8f |
__u32 flags = 0;
|
|
|
99be8f |
__u32 mtf = 0;
|
|
|
99be8f |
@@ -640,9 +650,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
|
|
|
99be8f |
__u16 vid;
|
|
|
99be8f |
|
|
|
99be8f |
NEXT_ARG();
|
|
|
99be8f |
- if (eth_type != htons(ETH_P_8021Q)) {
|
|
|
99be8f |
- fprintf(stderr,
|
|
|
99be8f |
- "Can't set \"vlan_id\" if ethertype isn't 802.1Q\n");
|
|
|
99be8f |
+ if (!eth_type_vlan(eth_type)) {
|
|
|
99be8f |
+ fprintf(stderr, "Can't set \"vlan_id\" if ethertype isn't 802.1Q or 802.1AD\n");
|
|
|
99be8f |
return -1;
|
|
|
99be8f |
}
|
|
|
99be8f |
ret = get_u16(&vid, *argv, 10);
|
|
|
99be8f |
@@ -655,9 +664,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
|
|
|
99be8f |
__u8 vlan_prio;
|
|
|
99be8f |
|
|
|
99be8f |
NEXT_ARG();
|
|
|
99be8f |
- if (eth_type != htons(ETH_P_8021Q)) {
|
|
|
99be8f |
- fprintf(stderr,
|
|
|
99be8f |
- "Can't set \"vlan_prio\" if ethertype isn't 802.1Q\n");
|
|
|
99be8f |
+ if (!eth_type_vlan(eth_type)) {
|
|
|
99be8f |
+ fprintf(stderr, "Can't set \"vlan_prio\" if ethertype isn't 802.1Q or 802.1AD\n");
|
|
|
99be8f |
return -1;
|
|
|
99be8f |
}
|
|
|
99be8f |
ret = get_u8(&vlan_prio, *argv, 10);
|
|
|
99be8f |
@@ -674,6 +682,42 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
|
|
|
99be8f |
&vlan_ethtype, n);
|
|
|
99be8f |
if (ret < 0)
|
|
|
99be8f |
return -1;
|
|
|
99be8f |
+ } else if (matches(*argv, "cvlan_id") == 0) {
|
|
|
99be8f |
+ __u16 vid;
|
|
|
99be8f |
+
|
|
|
99be8f |
+ NEXT_ARG();
|
|
|
99be8f |
+ if (!eth_type_vlan(vlan_ethtype)) {
|
|
|
99be8f |
+ fprintf(stderr, "Can't set \"cvlan_id\" if inner vlan ethertype isn't 802.1Q or 802.1AD\n");
|
|
|
99be8f |
+ return -1;
|
|
|
99be8f |
+ }
|
|
|
99be8f |
+ ret = get_u16(&vid, *argv, 10);
|
|
|
99be8f |
+ if (ret < 0 || vid & ~0xfff) {
|
|
|
99be8f |
+ fprintf(stderr, "Illegal \"cvlan_id\"\n");
|
|
|
99be8f |
+ return -1;
|
|
|
99be8f |
+ }
|
|
|
99be8f |
+ addattr16(n, MAX_MSG, TCA_FLOWER_KEY_CVLAN_ID, vid);
|
|
|
99be8f |
+ } else if (matches(*argv, "cvlan_prio") == 0) {
|
|
|
99be8f |
+ __u8 cvlan_prio;
|
|
|
99be8f |
+
|
|
|
99be8f |
+ NEXT_ARG();
|
|
|
99be8f |
+ if (!eth_type_vlan(vlan_ethtype)) {
|
|
|
99be8f |
+ fprintf(stderr, "Can't set \"cvlan_prio\" if inner vlan ethertype isn't 802.1Q or 802.1AD\n");
|
|
|
99be8f |
+ return -1;
|
|
|
99be8f |
+ }
|
|
|
99be8f |
+ ret = get_u8(&cvlan_prio, *argv, 10);
|
|
|
99be8f |
+ if (ret < 0 || cvlan_prio & ~0x7) {
|
|
|
99be8f |
+ fprintf(stderr, "Illegal \"cvlan_prio\"\n");
|
|
|
99be8f |
+ return -1;
|
|
|
99be8f |
+ }
|
|
|
99be8f |
+ addattr8(n, MAX_MSG,
|
|
|
99be8f |
+ TCA_FLOWER_KEY_CVLAN_PRIO, cvlan_prio);
|
|
|
99be8f |
+ } else if (matches(*argv, "cvlan_ethtype") == 0) {
|
|
|
99be8f |
+ NEXT_ARG();
|
|
|
99be8f |
+ ret = flower_parse_vlan_eth_type(*argv, vlan_ethtype,
|
|
|
99be8f |
+ TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
|
|
|
99be8f |
+ &cvlan_ethtype, n);
|
|
|
99be8f |
+ if (ret < 0)
|
|
|
99be8f |
+ return -1;
|
|
|
99be8f |
} else if (matches(*argv, "dst_mac") == 0) {
|
|
|
99be8f |
NEXT_ARG();
|
|
|
99be8f |
ret = flower_parse_eth_addr(*argv,
|
|
|
99be8f |
@@ -696,7 +740,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
|
|
|
99be8f |
}
|
|
|
99be8f |
} else if (matches(*argv, "ip_proto") == 0) {
|
|
|
99be8f |
NEXT_ARG();
|
|
|
99be8f |
- ret = flower_parse_ip_proto(*argv, vlan_ethtype ?
|
|
|
99be8f |
+ ret = flower_parse_ip_proto(*argv, cvlan_ethtype ?
|
|
|
99be8f |
+ cvlan_ethtype : vlan_ethtype ?
|
|
|
99be8f |
vlan_ethtype : eth_type,
|
|
|
99be8f |
TCA_FLOWER_KEY_IP_PROTO,
|
|
|
99be8f |
&ip_proto, n);
|
|
|
99be8f |
@@ -726,7 +771,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
|
|
|
99be8f |
}
|
|
|
99be8f |
} else if (matches(*argv, "dst_ip") == 0) {
|
|
|
99be8f |
NEXT_ARG();
|
|
|
99be8f |
- ret = flower_parse_ip_addr(*argv, vlan_ethtype ?
|
|
|
99be8f |
+ ret = flower_parse_ip_addr(*argv, cvlan_ethtype ?
|
|
|
99be8f |
+ cvlan_ethtype : vlan_ethtype ?
|
|
|
99be8f |
vlan_ethtype : eth_type,
|
|
|
99be8f |
TCA_FLOWER_KEY_IPV4_DST,
|
|
|
99be8f |
TCA_FLOWER_KEY_IPV4_DST_MASK,
|
|
|
99be8f |
@@ -739,7 +785,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
|
|
|
99be8f |
}
|
|
|
99be8f |
} else if (matches(*argv, "src_ip") == 0) {
|
|
|
99be8f |
NEXT_ARG();
|
|
|
99be8f |
- ret = flower_parse_ip_addr(*argv, vlan_ethtype ?
|
|
|
99be8f |
+ ret = flower_parse_ip_addr(*argv, cvlan_ethtype ?
|
|
|
99be8f |
+ cvlan_ethtype : vlan_ethtype ?
|
|
|
99be8f |
vlan_ethtype : eth_type,
|
|
|
99be8f |
TCA_FLOWER_KEY_IPV4_SRC,
|
|
|
99be8f |
TCA_FLOWER_KEY_IPV4_SRC_MASK,
|
|
|
99be8f |
@@ -1234,6 +1281,34 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
|
|
|
99be8f |
fprintf(f, "\n vlan_prio %d", rta_getattr_u8(attr));
|
|
|
99be8f |
}
|
|
|
99be8f |
|
|
|
99be8f |
+ if (tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]) {
|
|
|
99be8f |
+ SPRINT_BUF(buf);
|
|
|
99be8f |
+ struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE];
|
|
|
99be8f |
+
|
|
|
99be8f |
+ fprintf(f, "\n vlan_ethtype %s",
|
|
|
99be8f |
+ ll_proto_n2a(rta_getattr_u16(attr), buf, sizeof(buf)));
|
|
|
99be8f |
+ }
|
|
|
99be8f |
+
|
|
|
99be8f |
+ if (tb[TCA_FLOWER_KEY_CVLAN_ID]) {
|
|
|
99be8f |
+ struct rtattr *attr = tb[TCA_FLOWER_KEY_CVLAN_ID];
|
|
|
99be8f |
+
|
|
|
99be8f |
+ fprintf(f, "\n cvlan_id %u", rta_getattr_u16(attr));
|
|
|
99be8f |
+ }
|
|
|
99be8f |
+
|
|
|
99be8f |
+ if (tb[TCA_FLOWER_KEY_CVLAN_PRIO]) {
|
|
|
99be8f |
+ struct rtattr *attr = tb[TCA_FLOWER_KEY_CVLAN_PRIO];
|
|
|
99be8f |
+
|
|
|
99be8f |
+ fprintf(f, "\n cvlan_prio %d", rta_getattr_u8(attr));
|
|
|
99be8f |
+ }
|
|
|
99be8f |
+
|
|
|
99be8f |
+ if (tb[TCA_FLOWER_KEY_CVLAN_ETH_TYPE]) {
|
|
|
99be8f |
+ SPRINT_BUF(buf);
|
|
|
99be8f |
+ struct rtattr *attr = tb[TCA_FLOWER_KEY_CVLAN_ETH_TYPE];
|
|
|
99be8f |
+
|
|
|
99be8f |
+ fprintf(f, "\n cvlan_ethtype %s",
|
|
|
99be8f |
+ ll_proto_n2a(rta_getattr_u16(attr), buf, sizeof(buf)));
|
|
|
99be8f |
+ }
|
|
|
99be8f |
+
|
|
|
99be8f |
flower_print_eth_addr(f, "dst_mac", tb[TCA_FLOWER_KEY_ETH_DST],
|
|
|
99be8f |
tb[TCA_FLOWER_KEY_ETH_DST_MASK]);
|
|
|
99be8f |
flower_print_eth_addr(f, "src_mac", tb[TCA_FLOWER_KEY_ETH_SRC],
|
|
|
99be8f |
--
|
|
|
99be8f |
2.20.1
|
|
|
99be8f |
|