From: Wojciech Drewek Date: Fri, 29 Jul 2022 08:50:35 +0000 (+0200) Subject: f_flower: Introduce PPPoE support X-Git-Tag: v6.0.0~23^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e3e17c25f6291a03714f921ad9e9a4615246bf91;p=thirdparty%2Fiproute2.git 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 Acked-by: Guillaume Nault Signed-off-by: David Ahern --- 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 #include #include +#include #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),