From patchwork Sat Jul 2 14:34:25 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jamal Hadi Salim X-Patchwork-Id: 643496 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3rhbQb2QfBz9sdn for ; Sun, 3 Jul 2016 00:34:47 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=mojatatu-com.20150623.gappssmtp.com header.i=@mojatatu-com.20150623.gappssmtp.com header.b=bJsRzcAU; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751688AbcGBOei (ORCPT ); Sat, 2 Jul 2016 10:34:38 -0400 Received: from mail-it0-f67.google.com ([209.85.214.67]:34509 "EHLO mail-it0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751360AbcGBOeh (ORCPT ); Sat, 2 Jul 2016 10:34:37 -0400 Received: by mail-it0-f67.google.com with SMTP id f6so4921392ith.1 for ; Sat, 02 Jul 2016 07:34:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mojatatu-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=76Apd2PEPVPgSS+Np90+UuoSwIeJMG4Q8ZpcGeAI1Xs=; b=bJsRzcAUYSqJiw/Owr7MDF0/EB+pH/r1FzRLZziuw9IaRZIEDAH5eINv0hrTlAKKKN 7yKM55sptntwe0V0FixstYrE+BSELMfNlRcR0Vc8WnV9VHNoK0U+KRdkeFJv6nG2O3p1 bDbmFHO0U/t/E5nTW7v1BFObl9Gd5c12X+S4sbZeRaYNEyO2YnBmNIDTGMbu1c21tHx4 gnD25FeA9pMQnNZTR0XavOI9rDGhJpS6aAeRn3pPCkuwrH+1cy0KSndL5W+z+/uGwfa/ kUIo0WcNZeA3n2t/ZVRXNRehUqO+u1hSIlwkT95xQ9fw1jXDVIo0tc2mLZkjWKCSNG4s 1q2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=76Apd2PEPVPgSS+Np90+UuoSwIeJMG4Q8ZpcGeAI1Xs=; b=IPQKqaD6UBOfEFMOamdSyjJNP3hm1xglQs7e/HxYhOYndLbq4tnreTsHzKIQ9/7bxC LrPQK5qhMEqn7Yb8VIqbRBPD/LS2h6MI8B4VZk5jHXAc+0yCm9Iiu0H2LvbyhVDDDh7c Ccrnq7rti7j6frQxGLP1UikrhtPspNgkhbJyaYRxAvMNXtE6FSGPCurKCg7SkaqHl2uD T5mqlsNboVWfzEQu4OrLR+Jr4adYQk68Im7djodbSmb8GC+8ZAc7jDSB8+OP6REHeCR2 VbLBSXE/y8s9dKQ48sKMoFCONh7HEMcW0nnQGlHNkopUqkwu+UYqI9jSXZfto6pOouML BHhA== X-Gm-Message-State: ALyK8tJtYifkm635qPEun+f4YQG4PsXfmbdG26XHlBQ/V4UpMKhs/7jEeU604TLsjYDr/Q== X-Received: by 10.36.227.67 with SMTP id d64mr2991924ith.18.1467470076219; Sat, 02 Jul 2016 07:34:36 -0700 (PDT) Received: from jhs-UX303LB.lan ([23.233.30.50]) by smtp.gmail.com with ESMTPSA id z205sm15127566itc.11.2016.07.02.07.34.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 02 Jul 2016 07:34:35 -0700 (PDT) From: Jamal Hadi Salim X-Google-Original-From: Jamal Hadi Salim To: davem@davemloft.net Cc: netdev@vger.kernel.org, daniel@iogearbox.net, xiyou.wangcong@gmail.com, nikolay@cumulusnetworks.com, Jamal Hadi Salim Subject: [PATCH v2 net-next 1/1] net sched actions: mirred add support for setting Dst MAC address Date: Sat, 2 Jul 2016 10:34:25 -0400 Message-Id: <1467470065-17613-1-git-send-email-jhs@emojatatu.com> X-Mailer: git-send-email 1.9.1 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Jamal Hadi Salim Often redirecting or mirroring requires that we set the dstMAC address of the target device. While it is possible to pipe to a pedit action, this patch obsoletes the need for that. This is a justified feature because the dst MAC addresses rewrite is such a common use case. Sample usage: sudo $TC filter add dev $ETH parent 1: protocol ip prio 10 \ u32 match ip protocol 1 0xff flowid 1:2 \ action mirred egress redirect dev $SPANPORT dst 02:15:15:15:15:15 This will match all icmp packets going out on dev $ETH and redirect them to dev $SPANPORT while setting their dst MAC address to 02:15:15:15:15:15 Signed-off-by: Jamal Hadi Salim Reviewed-by: Nikolay Aleksandrov --- include/net/tc_act/tc_mirred.h | 4 +++- include/uapi/linux/tc_act/tc_mirred.h | 7 ++++--- net/sched/act_mirred.c | 24 +++++++++++++++++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h index e891835..7e8bced 100644 --- a/include/net/tc_act/tc_mirred.h +++ b/include/net/tc_act/tc_mirred.h @@ -6,10 +6,12 @@ struct tcf_mirred { struct tcf_common common; + struct net_device __rcu *tcfm_dev; int tcfm_eaction; int tcfm_ifindex; int tcfm_ok_push; - struct net_device __rcu *tcfm_dev; + u8 eth_dst[ETH_ALEN]; + /* XXX 6 bytes hole here*/ struct list_head tcfm_list; }; #define to_mirred(a) \ diff --git a/include/uapi/linux/tc_act/tc_mirred.h b/include/uapi/linux/tc_act/tc_mirred.h index 3d7a2b3..aaca1ff 100644 --- a/include/uapi/linux/tc_act/tc_mirred.h +++ b/include/uapi/linux/tc_act/tc_mirred.h @@ -9,20 +9,21 @@ #define TCA_EGRESS_MIRROR 2 /* mirror packet to EGRESS */ #define TCA_INGRESS_REDIR 3 /* packet redirect to INGRESS*/ #define TCA_INGRESS_MIRROR 4 /* mirror packet to INGRESS */ - + struct tc_mirred { tc_gen; int eaction; /* one of IN/EGRESS_MIRROR/REDIR */ __u32 ifindex; /* ifindex of egress port */ }; - + enum { TCA_MIRRED_UNSPEC, TCA_MIRRED_TM, TCA_MIRRED_PARMS, TCA_MIRRED_PAD, + TCA_MIRRED_DMAC, __TCA_MIRRED_MAX }; #define TCA_MIRRED_MAX (__TCA_MIRRED_MAX - 1) - + #endif diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 5b135d3..1cc14f5 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -49,6 +49,7 @@ static void tcf_mirred_release(struct tc_action *a, int bind) static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = { [TCA_MIRRED_PARMS] = { .len = sizeof(struct tc_mirred) }, + [TCA_MIRRED_DMAC] = { .len = ETH_ALEN}, }; static int mirred_net_id; @@ -64,15 +65,24 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, struct net_device *dev; int ret, ok_push = 0; bool exists = false; + u8 *daddr = NULL; if (nla == NULL) return -EINVAL; + ret = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy); if (ret < 0) return ret; + if (tb[TCA_MIRRED_PARMS] == NULL) return -EINVAL; + parm = nla_data(tb[TCA_MIRRED_PARMS]); + if (tb[TCA_MIRRED_DMAC]) { + daddr = nla_data(tb[TCA_MIRRED_DMAC]); + if (is_zero_ether_addr(daddr)) + return -EINVAL; + } exists = tcf_hash_check(tn, parm->index, a, bind); if (exists && bind) @@ -126,6 +136,9 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, } m = to_mirred(a); + if (daddr) + ether_addr_copy(m->eth_dst, daddr); + ASSERT_RTNL(); m->tcf_action = parm->action; m->tcfm_eaction = parm->eaction; @@ -190,6 +203,9 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, skb2->skb_iif = skb->dev->ifindex; skb2->dev = dev; + if (!is_zero_ether_addr(m->eth_dst)) + ether_addr_copy(eth_hdr(skb2)->h_dest, m->eth_dst); + err = dev_queue_xmit(skb2); if (err) { @@ -203,7 +219,8 @@ out: return retval; } -static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) +static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, + int ref) { unsigned char *b = skb_tail_pointer(skb); struct tcf_mirred *m = a->priv; @@ -220,6 +237,11 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, i if (nla_put(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt)) goto nla_put_failure; + if (!is_zero_ether_addr(m->eth_dst)) { + if (nla_put(skb, TCA_MIRRED_DMAC, ETH_ALEN, m->eth_dst)) + goto nla_put_failure; + } + tcf_tm_dump(&t, &m->tcf_tm); if (nla_put_64bit(skb, TCA_MIRRED_TM, sizeof(t), &t, TCA_MIRRED_PAD)) goto nla_put_failure;