aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWojciech Drewek <wojciech.drewek@intel.com>2022-07-29 10:50:35 +0200
committerDavid Ahern <dsahern@kernel.org>2022-07-29 11:23:22 -0600
commite3e17c25f6291a03714f921ad9e9a4615246bf91 (patch)
treeadbb0740e2d39c9a13a45ce600cf91e33ed6bbca
parent5a56804ce1d4539d14f8fb44178e499a7ae2aa74 (diff)
downloadiproute2-e3e17c25f6291a03714f921ad9e9a4615246bf91.tar.gz
f_flower: Introduce PPPoE support
Introduce PPPoE specific fields in tc-flower: - session id (16 bits) - ppp protocol (16 bits) Those fields can be provided only when protocol was set to ETH_P_PPP_SES. ppp_proto works similar to vlan_ethtype, i.e. ppp_proto overwrites eth_type. Thanks to that, fields from encapsulated protocols (such as src_ip) can be specified. e.g. # tc filter add dev ens6f0 ingress prio 1 protocol ppp_ses \ flower \ pppoe_sid 1234 \ ppp_proto ip \ dst_ip 127.0.0.1 \ src_ip 127.0.0.2 \ action drop Vlan and cvlan is also supported, in this case cvlan_ethtype or vlan_ethtype has to be set to ETH_P_PPP_SES. e.g. # tc filter add dev ens6f0 ingress prio 1 protocol 802.1Q \ flower \ vlan_id 2 \ vlan_ethtype ppp_ses \ pppoe_sid 1234 \ ppp_proto ip \ dst_ip 127.0.0.1 \ src_ip 127.0.0.2 \ action drop Signed-off-by: Wojciech Drewek <wojciech.drewek@intel.com> Acked-by: Guillaume Nault <gnault@redhat.com> Signed-off-by: David Ahern <dsahern@kernel.org>
-rw-r--r--include/uapi/linux/pkt_cls.h3
-rw-r--r--man/man8/tc-flower.817
-rw-r--r--tc/f_flower.c58
3 files changed, 77 insertions, 1 deletions
diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 9a2ee1e39..a67dcd829 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -589,6 +589,9 @@ enum {
TCA_FLOWER_KEY_NUM_OF_VLANS, /* u8 */
+ TCA_FLOWER_KEY_PPPOE_SID, /* u16 */
+ TCA_FLOWER_KEY_PPP_PROTO, /* be16 */
+
__TCA_FLOWER_MAX,
};
diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8
index 523935242..5e486ea31 100644
--- a/man/man8/tc-flower.8
+++ b/man/man8/tc-flower.8
@@ -40,6 +40,10 @@ flower \- flow based traffic control filter
.IR PRIORITY " | "
.BR cvlan_ethtype " { " ipv4 " | " ipv6 " | "
.IR ETH_TYPE " } | "
+.B pppoe_sid
+.IR PSID " | "
+.BR ppp_proto " { " ip " | " ipv6 " | " mpls_uc " | " mpls_mc " | "
+.IR PPP_PROTO " } | "
.B mpls
.IR LSE_LIST " | "
.B mpls_label
@@ -202,7 +206,18 @@ Match on QinQ layer three protocol.
may be either
.BR ipv4 ", " ipv6
or an unsigned 16bit value in hexadecimal format.
-
+.TP
+.BI pppoe_sid " PSID"
+Match on PPPoE session id.
+.I PSID
+is an unsigned 16bit value in decimal format.
+.TP
+.BI ppp_proto " PPP_PROTO"
+Match on PPP layer three protocol.
+.I PPP_PROTO
+may be either
+.BR ip ", " ipv6 ", " mpls_uc ", " mpls_mc
+or an unsigned 16bit value in hexadecimal format.
.TP
.BI mpls " LSE_LIST"
Match on the MPLS label stack.
diff --git a/tc/f_flower.c b/tc/f_flower.c
index 622ec321f..069896a48 100644
--- a/tc/f_flower.c
+++ b/tc/f_flower.c
@@ -20,6 +20,7 @@
#include <linux/ip.h>
#include <linux/tc_act/tc_vlan.h>
#include <linux/mpls.h>
+#include <linux/ppp_defs.h>
#include "utils.h"
#include "tc_util.h"
@@ -55,6 +56,8 @@ static void explain(void)
" cvlan_id VID |\n"
" cvlan_prio PRIORITY |\n"
" cvlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n"
+ " pppoe_sid PSID |\n"
+ " ppp_proto [ ipv4 | ipv6 | mpls_uc | mpls_mc | PPP_PROTO ]"
" dst_mac MASKED-LLADDR |\n"
" src_mac MASKED-LLADDR |\n"
" ip_proto [tcp | udp | sctp | icmp | icmpv6 | IP-PROTO ] |\n"
@@ -1887,6 +1890,43 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
fprintf(stderr, "Illegal \"arp_sha\"\n");
return -1;
}
+
+ } else if (!strcmp(*argv, "pppoe_sid")) {
+ __be16 sid;
+
+ NEXT_ARG();
+ if (eth_type != htons(ETH_P_PPP_SES)) {
+ fprintf(stderr,
+ "Can't set \"pppoe_sid\" if ethertype isn't PPPoE session\n");
+ return -1;
+ }
+ ret = get_be16(&sid, *argv, 10);
+ if (ret < 0) {
+ fprintf(stderr, "Illegal \"pppoe_sid\"\n");
+ return -1;
+ }
+ addattr16(n, MAX_MSG, TCA_FLOWER_KEY_PPPOE_SID, sid);
+ } else if (!strcmp(*argv, "ppp_proto")) {
+ __be16 proto;
+
+ NEXT_ARG();
+ if (eth_type != htons(ETH_P_PPP_SES)) {
+ fprintf(stderr,
+ "Can't set \"ppp_proto\" if ethertype isn't PPPoE session\n");
+ return -1;
+ }
+ if (ppp_proto_a2n(&proto, *argv))
+ invarg("invalid ppp_proto", *argv);
+ /* get new ethtype for later parsing */
+ if (proto == htons(PPP_IP))
+ eth_type = htons(ETH_P_IP);
+ else if (proto == htons(PPP_IPV6))
+ eth_type = htons(ETH_P_IPV6);
+ else if (proto == htons(PPP_MPLS_UC))
+ eth_type = htons(ETH_P_MPLS_UC);
+ else if (proto == htons(PPP_MPLS_MC))
+ eth_type = htons(ETH_P_MPLS_MC);
+ addattr16(n, MAX_MSG, TCA_FLOWER_KEY_PPP_PROTO, proto);
} else if (matches(*argv, "enc_dst_ip") == 0) {
NEXT_ARG();
ret = flower_parse_ip_addr(*argv, 0,
@@ -2851,6 +2891,24 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
flower_print_eth_addr("arp_tha", tb[TCA_FLOWER_KEY_ARP_THA],
tb[TCA_FLOWER_KEY_ARP_THA_MASK]);
+ if (tb[TCA_FLOWER_KEY_PPPOE_SID]) {
+ struct rtattr *attr = tb[TCA_FLOWER_KEY_PPPOE_SID];
+
+ print_nl();
+ print_uint(PRINT_ANY, "pppoe_sid", " pppoe_sid %u",
+ rta_getattr_be16(attr));
+ }
+
+ if (tb[TCA_FLOWER_KEY_PPP_PROTO]) {
+ SPRINT_BUF(buf);
+ struct rtattr *attr = tb[TCA_FLOWER_KEY_PPP_PROTO];
+
+ print_nl();
+ print_string(PRINT_ANY, "ppp_proto", " ppp_proto %s",
+ ppp_proto_n2a(rta_getattr_u16(attr),
+ buf, sizeof(buf)));
+ }
+
flower_print_ip_addr("enc_dst_ip",
tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK] ?
htons(ETH_P_IP) : htons(ETH_P_IPV6),