From patchwork Wed Jul 8 16:10:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: William Tu X-Patchwork-Id: 1325298 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.133; helo=hemlock.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=ffGYouOI; dkim-atps=neutral Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4B246n5HRcz9sRf for ; Thu, 9 Jul 2020 02:11:13 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 08F2189791; Wed, 8 Jul 2020 16:11:12 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 3+NRkvsDApT3; Wed, 8 Jul 2020 16:11:09 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by hemlock.osuosl.org (Postfix) with ESMTP id DAFEE8978A; Wed, 8 Jul 2020 16:11:09 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id BFFEEC077B; Wed, 8 Jul 2020 16:11:09 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id E5CF2C016F for ; Wed, 8 Jul 2020 16:11:07 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id D358088F47 for ; Wed, 8 Jul 2020 16:11:07 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id dpsEqZM+OHod for ; Wed, 8 Jul 2020 16:11:06 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mail-pg1-f193.google.com (mail-pg1-f193.google.com [209.85.215.193]) by whitealder.osuosl.org (Postfix) with ESMTPS id 7C7DF88F4C for ; Wed, 8 Jul 2020 16:11:05 +0000 (UTC) Received: by mail-pg1-f193.google.com with SMTP id g67so20995923pgc.8 for ; Wed, 08 Jul 2020 09:11:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=bNKXVuog5TDKqwxNf9NT/mAqauITOhUzTmJiMUw0JGA=; b=ffGYouOIwF3Leuk2fwlmANMXB3A3ESagC6KbXx7SaPnWGPY581ThsY7t8KT15jv6f9 PvUD3miNynCRr3oNiwdEZmEF9/xwCpo1mJ+SEdpaLuNiAYTv5XKhXG1oX8GdS2f8mVEp xV/FDosRlaNhspnncB4bYxpWiuzeLxCLrgqcFNUl0BfkIcEypPQwxfdFdcXScK97Qdn3 A8qjK7bURgXdjrO1C7dLFBpBxAfqFSsgruLoF8879d25cbeoy/wIwaS7079887onhfHP eNSH1du+GnKyhfiR0q1V34yjrXCyfJzVG4tCjmzk/GFJNLjhWw0X8CuM0FoolTlCLKAb 2tqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=bNKXVuog5TDKqwxNf9NT/mAqauITOhUzTmJiMUw0JGA=; b=WmVlbl4Cz0WBbJR8dCthwGD3MoI/pVVPiQaOumROWY6svEk+XNKMy+Gg5BeYIg+kgP RwsibFmagMRaaKaRGmnXVlIZu3kLx2VeFm0/W/EZZEm1j/ARXXZtIFqItJA3yyfqGfi6 8tmDxEh+1mHxX6lWsRcKHxjpGjv1DZHpAJhxUq+It7OrPFS1wbj35EIi84huRDdiewO0 /XFLIBqWqMaibCSvw5sML8xmivU9ok64id/JFp5o1jkgfu5K2GG5HE0glGmlOPWvEl9q pPcbq5bM9CU8a5IOKvD1xNdi7wqzGHz+dDLkEjDxQiERWq2bJ1TizZyz+xnzAi8zyDu4 l+Bw== X-Gm-Message-State: AOAM531GEhNACBYmcT3Bbi1Ek81YwsCwrZU1T18sDeyh4NQTsHhCJOTD /ARzzz/l8JLYE2ENKD+BcEfO3O9CrdQ= X-Google-Smtp-Source: ABdhPJyvwdDsw0oxcF2QMaYcO6eEmoIilM5EAECUrIU4i2QHIr2yrXjzLtovt6QT6H+79yy++BtVzw== X-Received: by 2002:a63:e24d:: with SMTP id y13mr45329326pgj.248.1594224664514; Wed, 08 Jul 2020 09:11:04 -0700 (PDT) Received: from sc9-mailhost2.vmware.com (c-76-21-95-192.hsd1.ca.comcast.net. [76.21.95.192]) by smtp.gmail.com with ESMTPSA id j2sm6597707pjy.1.2020.07.08.09.11.03 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 08 Jul 2020 09:11:03 -0700 (PDT) From: William Tu To: dev@openvswitch.org Date: Wed, 8 Jul 2020 09:10:36 -0700 Message-Id: <1594224636-42337-4-git-send-email-u9012063@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1594224636-42337-1-git-send-email-u9012063@gmail.com> References: <1594224636-42337-1-git-send-email-u9012063@gmail.com> Cc: simon.horman@netronome.com, i.maximets@ovn.org, elibr@mellanox.com Subject: [ovs-dev] [PATCH 3/3] netdev-offload-tc: Add VxLAN encap support. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" The patch adds VxLAN encap tc-offload support. The userspace datapath, dpif-netdev, flow format differs than the kernel datapath in case of tunnel encap. Unlike kernel, the dpif-netdev does not use set and output action, but uses a single clone action with all the tunnel info nested inside. As an exmaple blow: actions:clone(tnl_push(tnl_port(5), header(size=50,type=4,eth(dst=06:1d:6e:a3:f1:61,src=26:df:25:f6:7b:4f,dl_type=0x0800), ipv4(src=172.31.1.100,dst=172.31.1.1,proto=17,tos=0,ttl=64,frag=0x4000), udp(src=0,dst=4789,csum=0x0), vxlan(flags=0x8000000,vni=0x0)),out_port(2) ), 3) The patch parses the above tunnel encap format and passes to the tc for offloading the VxLAN tunnel. Example of tc format: $ tc -s filter show dev ovs-p1 ingress filter protocol ip pref 3 flower chain 0 filter protocol ip pref 3 flower chain 0 handle 0x1 dst_mac 56:2a:1f:3c:bb:f2 src_mac 96:0c:a7:b0:60:a4 eth_type ipv4 ip_tos 0/0x3 ip_flags nofrag skip_hw not_in_hw action order 1: tunnel_key set src_ip 172.31.1.100 dst_ip 172.31.1.1 key_id 0 dst_port 4789 nocsum ttl 64 pipe index 2 ref 1 bind 1 installed 0 sec used 0 sec Action statistics: Sent 168 bytes 2 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 no_percpu action order 2: mirred (Egress Redirect to device ovs-p0) stolen index 2 ref 1 bind 1 installed 0 sec used 0 sec Action statistics: Sent 168 bytes 2 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 cookie b46e99079448ce581d0fe7a9853c0bb5 no_percpu Signed-off-by: William Tu --- lib/netdev-offload-tc.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index 2c9c6f4cae8b..a1deeb2b3040 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -1114,6 +1114,118 @@ parse_put_flow_ct_action(struct tc_flower *flower, } static int +parse_put_tnl_header(struct tc_flower *flower OVS_UNUSED, + struct tc_action *action, + const struct ovs_action_push_tnl *data) +{ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); + const struct eth_header *eth; + const struct udp_header *udp; + const void *l3; + const void *l4; + struct ds ds; + + ds_init(&ds); + eth = (const struct eth_header *)data->header; + l3 = eth + 1; + + if (eth->eth_type == htons(ETH_TYPE_IP)) { + const struct ip_header *ip = l3; + action->encap.ipv4.ipv4_src = get_16aligned_be32(&ip->ip_src); + action->encap.ipv4.ipv4_dst = get_16aligned_be32(&ip->ip_dst); + action->encap.ttl = ip->ip_ttl; + l4 = (ip + 1); + } else { + const struct ovs_16aligned_ip6_hdr *ip6 = l3; + memcpy(&action->encap.ipv6.ipv6_src, &ip6->ip6_src, + sizeof ip6->ip6_src); + memcpy(&action->encap.ipv6.ipv6_dst, &ip6->ip6_dst, + sizeof ip6->ip6_dst); + l4 = (ip6 + 1); + } + + udp = (const struct udp_header *) l4; + + if (data->tnl_type == OVS_VPORT_TYPE_VXLAN) { + const struct vxlanhdr *vxh; + + vxh = (const struct vxlanhdr *)(udp + 1); + action->encap.tp_src = udp->udp_src; + action->encap.tp_dst = udp->udp_dst; + action->encap.id_present = true; + action->encap.no_csum = true; + action->encap.id = be32_to_be64(get_16aligned_be32(&vxh->vx_vni) >> 8); + + ds_put_format(&ds, "vxlan(flags=0x%"PRIx32",vni=0x%"PRIx32")", + ntohl(get_16aligned_be32(&vxh->vx_flags)), + ntohl(get_16aligned_be32(&vxh->vx_vni)) >> 8); + VLOG_DBG_RL(&rl, "%s", ds_cstr(&ds)); + } else { + VLOG_DBG_RL(&rl, "unsupported tunnel type: %d", data->tnl_type); + return EOPNOTSUPP; + } + + ds_destroy(&ds); + return 0; +} + +static int +parse_put_flow_clone_action(struct tc_flower *flower, + const struct netdev *netdev, + const struct nlattr *clone, + size_t clone_len) +{ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); + struct tc_action *action; + const struct nlattr *ca; + size_t ca_left; + int err; + + NL_ATTR_FOR_EACH_UNSAFE (ca, ca_left, clone, clone_len) { + action = &flower->actions[flower->action_count]; + switch (nl_attr_type(ca)) { + case OVS_ACTION_ATTR_TUNNEL_PUSH: { + const struct ovs_action_push_tnl *tnl_push = nl_attr_get(ca); + + err = parse_put_tnl_header(flower, action, tnl_push); + if (err) { + return err; + } + action->type = TC_ACT_ENCAP; + flower->action_count++; + } + break; + case OVS_ACTION_ATTR_OUTPUT: { + struct netdev *outdev; + const char *outdev_type; + + odp_port_t port = nl_attr_get_odp_port(ca); + outdev = netdev_ports_get(port, netdev_get_dpif_type(netdev)); + if (!outdev) { + VLOG_DBG_RL(&rl, "Can't find netdev for output port " + "%d inside clone().", port); + return ENODEV; + } + outdev_type = netdev_get_type(outdev); + action->out.ifindex_out = netdev_get_ifindex(outdev); + action->out.ingress = is_internal_port(outdev_type); + netdev_close(outdev); + + action->type = TC_ACT_OUTPUT; + flower->action_count++; + } + break; + default: + VLOG_WARN_RL(&rl, "unsupported action %d inside clone()", + nl_attr_type(ca)); + return EOPNOTSUPP; + break; + } + } + return 0; +} + +static int parse_put_flow_set_masked_action(struct tc_flower *flower, struct tc_action *action, const struct nlattr *set, @@ -1789,6 +1901,15 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, action->chain = nl_attr_get_u32(nla); flower.action_count++; recirc_act = true; + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CLONE) { + const struct nlattr *clone = nl_attr_get(nla); + const size_t clone_len = nl_attr_get_size(nla); + + err = parse_put_flow_clone_action(&flower, netdev, clone, + clone_len); + if (err) { + return err; + } } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_DROP) { action->type = TC_ACT_GOTO; action->chain = 0; /* 0 is reserved and not used by recirc. */