From patchwork Fri May 31 16:48:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Herbert X-Patchwork-Id: 1108469 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=herbertland.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=herbertland-com.20150623.gappssmtp.com header.i=@herbertland-com.20150623.gappssmtp.com header.b="pZPUTdoq"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 45Fr6B6vs4z9s3l for ; Sat, 1 Jun 2019 02:50:10 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726925AbfEaQuJ (ORCPT ); Fri, 31 May 2019 12:50:09 -0400 Received: from mail-pf1-f195.google.com ([209.85.210.195]:35739 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726037AbfEaQuJ (ORCPT ); Fri, 31 May 2019 12:50:09 -0400 Received: by mail-pf1-f195.google.com with SMTP id d126so6565795pfd.2 for ; Fri, 31 May 2019 09:50:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=herbertland-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=atbujOdDEZN67PK1uQ7CnCNFshCZPtSe7bRXOMuZsjw=; b=pZPUTdoq3oCmhnc+SXRARAxmwxTyiTgJoymXXm6df3np/D6hZ3UzAiVuEObJN53lON vzCDd5tSEeyisdgKl8ERfPcupMU2ANzaWJ+lktkzPq3lVRvC1F8MYAFILgY3+aqf6xAk T8MNnT+dUlCz9zPWTiYEDEBTTMeRi7lOb0UDyzjV2bs8av5NWIYzNFUq4y/EKV6U+ZDT 6/sSM5uLbQd/4coLxVdoboVwjL1yGFN/PSpORkphhljekKWcraQ/W+cp5cZ5XwZvLxr/ 5vd4/9S0jAYNaN/vVdapRXCk5/MRtfq7B77rgZPHW7nzS69Gvc9mDNe5kk/HNluwzpnT K4cw== 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=atbujOdDEZN67PK1uQ7CnCNFshCZPtSe7bRXOMuZsjw=; b=R+vVBOD7OrAXovOA2VMWLAKqmHF/d63DvjU9F8Bn5ts6l2BsH0UN3HfEAtsvQxyoGv 0WEFvtHKDfaAs9JBl7dRwh1jFa4pY37O1/eiSWQqlfUVU3PYCpuMfVROjuKtRyHH2aru ccXdNtrg/irG7JU5KHt2BInO+o8rBx8NrSC29HXLCZwmco1WzBNovDE7dfFp+GslcDtG AQFi86PyqxQU07hmnxqW9RnwVcUGGrJ/AVceB+i6IYze72/cbs1fnEbu5iycH6fHiM7p BmSgSX9TBNypOn/XDg8Dw29iFGJpG0/zJLNq+YDpsd/9U4cGWO1Avk8m9y+/62TxQnI2 vYVw== X-Gm-Message-State: APjAAAV3VD6pN3qBOia3pbccsxGPzgQQAOZtDufZ2B/xpdAUjOHdBAE1 47o1VfBbF4vuyp/ZE7oWPVQcUxO4taA= X-Google-Smtp-Source: APXvYqy4jBpooKGrKx6hrIM4p6SB+7xzW6hTVFTxuDeWbsMAZgC64YWs//6A9vDAIIvpfQeS2mpZ0Q== X-Received: by 2002:a17:90a:9f04:: with SMTP id n4mr10468227pjp.95.1559321408071; Fri, 31 May 2019 09:50:08 -0700 (PDT) Received: from localhost.localdomain (c-73-223-249-119.hsd1.ca.comcast.net. [73.223.249.119]) by smtp.gmail.com with ESMTPSA id e66sm8696835pfe.50.2019.05.31.09.50.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 31 May 2019 09:50:07 -0700 (PDT) From: Tom Herbert X-Google-Original-From: Tom Herbert To: davem@davemloft.net, netdev@vger.kernel.org, dlebrun@google.com, ahabdels.dev@gmail.com Cc: Tom Herbert Subject: [RFC PATCH 3/6] seg6: Obsolete unused SRH flags Date: Fri, 31 May 2019 09:48:37 -0700 Message-Id: <1559321320-9444-4-git-send-email-tom@quantonium.net> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1559321320-9444-1-git-send-email-tom@quantonium.net> References: <1559321320-9444-1-git-send-email-tom@quantonium.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Currently no flags are defined for segment routing in draft-ietf-6man-segment-routing-header-19. Mark them as being obsolete. The HMAC flag is the only one used by the stack. This needs additional consideration. Rewrite sr_has_hmac in uapi/linux/seg6.h to properly parse a segment routing header as opposed to relying on the now obsolete code. Implement seg6_find_hmac_tlv for internal stack use. That function parses (via __seg6_parse_srh) a TLV list and returns the pointer to an HMAC TLV if one exists. The parsing function also eliminates the assumption in seg6_get_tlv_hmac that the HMAC TLV must be the first TLV. Signed-off-by: Tom Herbert --- include/net/seg6.h | 12 +++++++++++- include/uapi/linux/seg6.h | 49 ++++++++++++++++++++++++++++++++++++++++------- net/ipv6/exthdrs.c | 2 +- net/ipv6/seg6.c | 12 ++++++++++-- net/ipv6/seg6_hmac.c | 8 +++----- net/ipv6/seg6_iptunnel.c | 4 ++-- 6 files changed, 69 insertions(+), 18 deletions(-) diff --git a/include/net/seg6.h b/include/net/seg6.h index 563d4a6..47e7c90 100644 --- a/include/net/seg6.h +++ b/include/net/seg6.h @@ -17,6 +17,7 @@ #include #include #include +#include #include static inline void update_csum_diff4(struct sk_buff *skb, __be32 from, @@ -67,11 +68,20 @@ extern void seg6_iptunnel_exit(void); extern int seg6_local_init(void); extern void seg6_local_exit(void); -extern bool __seg6_parse_srh(struct ipv6_sr_hdr *srh); +extern bool __seg6_parse_srh(struct ipv6_sr_hdr *srh, + struct sr6_tlv_hmac **hmacp); extern bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len); extern int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto); extern int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh); extern int seg6_lookup_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr, u32 tbl_id); + +static inline struct sr6_tlv_hmac *seg6_find_hmac_tlv(struct ipv6_sr_hdr *srh) +{ + struct sr6_tlv_hmac *hmacp = NULL; + + return __seg6_parse_srh(srh, &hmacp) ? hmacp : NULL; +} + #endif diff --git a/include/uapi/linux/seg6.h b/include/uapi/linux/seg6.h index 9117113..890420b0 100644 --- a/include/uapi/linux/seg6.h +++ b/include/uapi/linux/seg6.h @@ -33,11 +33,10 @@ struct ipv6_sr_hdr { struct in6_addr segments[0]; }; -#define SR6_FLAG1_PROTECTED (1 << 6) -#define SR6_FLAG1_OAM (1 << 5) -#define SR6_FLAG1_ALERT (1 << 4) -#define SR6_FLAG1_HMAC (1 << 3) - +#define SR6_FLAG1_PROTECTED (1 << 6) /* obsoleted */ +#define SR6_FLAG1_OAM (1 << 5) /* obsoleted */ +#define SR6_FLAG1_ALERT (1 << 4) /* obsoleted */ +#define SR6_FLAG1_HMAC (1 << 3) /* obsoleted */ #define SR6_TLV_INGRESS 1 /* obsoleted */ #define SR6_TLV_EGRESS 2 /* obsoleted */ @@ -47,12 +46,48 @@ struct ipv6_sr_hdr { #define SR6_TLV_PADDING 1 #define SR6_TLV_HMAC 5 -#define sr_has_hmac(srh) ((srh)->flags & SR6_FLAG1_HMAC) - struct sr6_tlv { __u8 type; __u8 len; __u8 data[0]; }; +static inline bool __sr_has_hmac(struct ipv6_sr_hdr *srh) +{ + unsigned char *opt = (unsigned char *)srh; + int len = (srh->hdrlen + 1) << 8; + unsigned int off; + + off = sizeof(*srh) + ((srh->first_segment + 1) << 4); + len -= off; + + while (len > 0) { + struct sr6_tlv *tlv; + unsigned int optlen; + + switch (opt[off]) { + case SR6_TLV_PAD1: + optlen = 1; + break; + case SR6_TLV_HMAC: + return true; + default: + if (len < sizeof(*tlv)) + return false; + + tlv = (struct sr6_tlv *)&opt[off]; + optlen = sizeof(*tlv) + tlv->len; + + break; + } + + off += optlen; + len -= optlen; + } + + return false; +} + +#define sr_has_hmac(srh) __sr_has_hmac(srh) + #endif diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 20291c2..112e2fd 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -922,7 +922,7 @@ static void ipv6_push_rthdr4(struct sk_buff *skb, u8 *proto, } #ifdef CONFIG_IPV6_SEG6_HMAC - if (sr_has_hmac(sr_phdr)) { + if (seg6_find_hmac_tlv(sr_phdr)) { struct net *net = NULL; if (skb->dev) diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c index e461357..1e782a6 100644 --- a/net/ipv6/seg6.c +++ b/net/ipv6/seg6.c @@ -30,7 +30,7 @@ #include #endif -bool __seg6_parse_srh(struct ipv6_sr_hdr *srh) +bool __seg6_parse_srh(struct ipv6_sr_hdr *srh, struct sr6_tlv_hmac **hmacp) { int len = ipv6_optlen((struct ipv6_opt_hdr *)srh); unsigned char *opt = (unsigned char *)srh; @@ -39,6 +39,8 @@ bool __seg6_parse_srh(struct ipv6_sr_hdr *srh) off = seg6_tlv_offset(srh); len -= off; + *hmacp = NULL; + while (len > 0) { struct sr6_tlv *tlv; unsigned int optlen; @@ -47,6 +49,10 @@ bool __seg6_parse_srh(struct ipv6_sr_hdr *srh) case SR6_TLV_PAD1: optlen = 1; break; + case SR6_TLV_HMAC: + if (!*hmacp) + *hmacp = (struct sr6_tlv_hmac *)&opt[off]; + /* Fall through */ default: if (len < sizeof(*tlv)) return false; @@ -66,6 +72,8 @@ bool __seg6_parse_srh(struct ipv6_sr_hdr *srh) bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len) { + struct sr6_tlv_hmac *hmacp; + if (srh->type != IPV6_SRCRT_TYPE_4) return false; @@ -75,7 +83,7 @@ bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len) if (srh->segments_left > srh->first_segment) return false; - return __seg6_parse_srh(srh); + return __seg6_parse_srh(srh, &hmacp); } static struct genl_family seg6_genl_family; diff --git a/net/ipv6/seg6_hmac.c b/net/ipv6/seg6_hmac.c index 8546f94..92b398c 100644 --- a/net/ipv6/seg6_hmac.c +++ b/net/ipv6/seg6_hmac.c @@ -95,13 +95,11 @@ static struct sr6_tlv_hmac *seg6_get_tlv_hmac(struct ipv6_sr_hdr *srh) if (srh->hdrlen < (srh->first_segment + 1) * 2 + 5) return NULL; - if (!sr_has_hmac(srh)) + tlv = seg6_find_hmac_tlv(srh); + if (!tlv) return NULL; - tlv = (struct sr6_tlv_hmac *) - ((char *)srh + ((srh->hdrlen + 1) << 3) - 40); - - if (tlv->tlvhdr.type != SR6_TLV_HMAC || tlv->tlvhdr.len != 38) + if (tlv->tlvhdr.len != sizeof(*tlv) - 2) return NULL; return tlv; diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c index 7a525fd..5344bee 100644 --- a/net/ipv6/seg6_iptunnel.c +++ b/net/ipv6/seg6_iptunnel.c @@ -161,7 +161,7 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) set_tun_src(net, dst->dev, &hdr->daddr, &hdr->saddr); #ifdef CONFIG_IPV6_SEG6_HMAC - if (sr_has_hmac(isrh)) { + if (seg6_find_hmac_tlv(isrh)) { err = seg6_push_hmac(net, &hdr->saddr, isrh); if (unlikely(err)) return err; @@ -211,7 +211,7 @@ int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh) hdr->daddr = isrh->segments[isrh->first_segment]; #ifdef CONFIG_IPV6_SEG6_HMAC - if (sr_has_hmac(isrh)) { + if (seg6_find_hmac_tlv(isrh)) { struct net *net = dev_net(skb_dst(skb)->dev); err = seg6_push_hmac(net, &hdr->saddr, isrh);