]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
f_flower: Introduce PPPoE support
authorWojciech Drewek <wojciech.drewek@intel.com>
Fri, 29 Jul 2022 08:50:35 +0000 (10:50 +0200)
committerDavid Ahern <dsahern@kernel.org>
Fri, 29 Jul 2022 17:23:22 +0000 (11:23 -0600)
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>
include/uapi/linux/pkt_cls.h
man/man8/tc-flower.8
tc/f_flower.c

index 9a2ee1e39fadf7dcf830bcb4d638526b950f1fe6..a67dcd8294c91631f19a15e775dfed2138a8b2b2 100644 (file)
@@ -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,
 };
 
index 523935242ccf68e0b4079cd24559fc705f2b6d59..5e486ea31d37f9897281722ed38b21b8956869d2 100644 (file)
@@ -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.
index 622ec321f310708bf67241d20ad702158de920b2..069896a48f332f1a6559b6592361e723e0dbc027 100644 (file)
@@ -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),