* The argument to src_mac and dst_mac may now take an optional mask
  to limit the scope of matching.
* This address is is documented as a LLADDR in keeping with ip-link(8).
* The formats accepted match those already output when dumping flower
  filters from the kernel.

Example of use of LLADDR with and without a mask:

tc qdisc add dev eth0 ingress
tc filter add dev eth0 protocol ip parent ffff: flower indev eth0 \
        src_mac 52:54:01:00:00:00/ff:ff:00:00:00:01 action drop
tc filter add dev eth0 protocol ip parent ffff: flower indev eth0 \
        src_mac 52:54:00:00:00:00/23 action drop
tc filter add dev eth0 protocol ip parent ffff: flower indev eth0 \
        src_mac 52:54:00:00:00:00 action drop

Signed-off-by: Simon Horman <simon.hor...@netronome.com>
---
 man/man8/tc-flower.8 | 13 +++++++++----
 tc/f_flower.c        | 43 ++++++++++++++++++++++++++++++++++++-------
 2 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8
index a383b6584dc6..31c7d3b32f9b 100644
--- a/man/man8/tc-flower.8
+++ b/man/man8/tc-flower.8
@@ -22,7 +22,7 @@ flower \- flow based traffic control filter
 .BR skip_sw " | " skip_hw
 .R " | { "
 .BR dst_mac " | " src_mac " } "
-.IR mac_address " | "
+.IR MASKED_LLADDR " | "
 .B vlan_id
 .IR VID " | "
 .B vlan_prio
@@ -74,10 +74,15 @@ filter, or TC offload is not enabled for the interface, 
operation will fail.
 .BI skip_hw
 Do not process filter by hardware.
 .TP
-.BI dst_mac " mac_address"
+.BI dst_mac " MASKED_LLADDR"
 .TQ
-.BI src_mac " mac_address"
-Match on source or destination MAC address.
+.BI src_mac " MASKED_LLADDR"
+Match on source or destination MAC address.  A mask may be optionally
+provided to limit the bits of the address which are matched. A mask is
+provided by following the address with a slash and then the mask. It may be
+provided in LLADDR format, in which case it is a bitwise mask, or as a
+number of high bits to match. If the mask is missing then a match on all
+bits is assumed.
 .TP
 .BI vlan_id " VID"
 Match on vlan tag id.
diff --git a/tc/f_flower.c b/tc/f_flower.c
index cdf74344f78f..6d9a3b70afed 100644
--- a/tc/f_flower.c
+++ b/tc/f_flower.c
@@ -45,8 +45,8 @@ static void explain(void)
                "                       vlan_id VID |\n"
                "                       vlan_prio PRIORITY |\n"
                "                       vlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] 
|\n"
-               "                       dst_mac MAC-ADDR |\n"
-               "                       src_mac MAC-ADDR |\n"
+               "                       dst_mac MASKED-LLADDR |\n"
+               "                       src_mac MASKED-LLADDR |\n"
                "                       ip_proto [tcp | udp | sctp | icmp | 
icmpv6 | IP-PROTO ] |\n"
                "                       dst_ip PREFIX |\n"
                "                       src_ip PREFIX |\n"
@@ -58,6 +58,7 @@ static void explain(void)
                "                       enc_src_ip PREFIX |\n"
                "                       enc_key_id [ KEY-ID ] }\n"
                "       FILTERID := X:Y:Z\n"
+               "       MASKED_LLADDR := { LLADDR | LLADDR/MASK | LLADDR/BITS 
}\n"
                "       ACTION-SPEC := ... look at individual actions\n"
                "\n"
                "NOTE: CLASSID, IP-PROTO are parsed as hexadecimal input.\n"
@@ -68,16 +69,44 @@ static void explain(void)
 static int flower_parse_eth_addr(char *str, int addr_type, int mask_type,
                                 struct nlmsghdr *n)
 {
-       int ret;
-       char addr[ETH_ALEN];
+       int ret, err = -1;
+       char addr[ETH_ALEN], *slash;
+
+       slash = strchr(str, '/');
+       if (slash)
+               *slash = '\0';
 
        ret = ll_addr_a2n(addr, sizeof(addr), str);
        if (ret < 0)
-               return -1;
+               goto err;
        addattr_l(n, MAX_MSG, addr_type, addr, sizeof(addr));
-       memset(addr, 0xff, ETH_ALEN);
+
+       if (slash) {
+               unsigned bits;
+
+               if (!get_unsigned(&bits, slash + 1, 10)) {
+                       uint64_t mask;
+
+                       /* Extra 16 bit shift to push mac address into
+                        * high bits of uint64_t
+                        */
+                       mask = htonll(0xffffffffffffULL << (16 + 48 - bits));
+                       memcpy(addr, &mask, ETH_ALEN);
+               } else {
+                       ret = ll_addr_a2n(addr, sizeof(addr), slash + 1);
+                       if (ret < 0)
+                               goto err;
+               }
+       } else {
+               memset(addr, 0xff, ETH_ALEN);
+       }
        addattr_l(n, MAX_MSG, mask_type, addr, sizeof(addr));
-       return 0;
+
+       err = 0;
+err:
+       if (slash)
+               *slash = '/';
+       return err;
 }
 
 static int flower_parse_vlan_eth_type(char *str, __be16 eth_type, int type,
-- 
2.7.0.rc3.207.g0ac5344

Reply via email to