[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220729085035.535788-4-wojciech.drewek@intel.com>
Date: Fri, 29 Jul 2022 10:50:35 +0200
From: Wojciech Drewek <wojciech.drewek@...el.com>
To: netdev@...r.kernel.org
Cc: dsahern@...il.com, stephen@...workplumber.org, gnault@...hat.com
Subject: [PATCH iproute-next v4 3/3] 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@...el.com>
---
v3: don't reject 0xffff session ID
---
include/uapi/linux/pkt_cls.h | 3 ++
man/man8/tc-flower.8 | 17 ++++++++++-
tc/f_flower.c | 58 ++++++++++++++++++++++++++++++++++++
3 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 9a2ee1e39fad..a67dcd8294c9 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 523935242ccf..5e486ea31d37 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 622ec321f310..069896a48f33 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),
--
2.31.1
Powered by blists - more mailing lists