From b4c8e306b3e226076d12128aae38ca94e9eb69be Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Fri, 17 Mar 2017 13:23:54 +0100 Subject: [PATCH] tc: flower: Allow *_mac options to accept a mask Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1422629 Upstream Status: iproute2.git commit c2078f8dc48c5 commit c2078f8dc48c572a5016c79c3a2a878b6e39e8ee Author: Simon Horman Date: Fri Dec 16 14:54:37 2016 +0100 tc: flower: Allow *_mac options to accept a mask * 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 --- 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 3841ff2..3310496 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 5d93568..2774905 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 [ IPV4-ADDR | IPV6-ADDR ] |\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, -- 1.8.3.1