Openvswitch attempts to use IPv6 packet parsing functions without any dependency on IPv6 (unlike every other place in kernel). Pull the IPv6 code in openvswitch togeter and put a conditional that's dependent on CONFIG_IPV6.
Resolves: net/built-in.o: In function `ovs_flow_extract': (.text+0xbf5d5): undefined reference to `ipv6_skip_exthdr' Signed-off-by: Vlad Yasevich <vyase...@redhat.com> --- net/openvswitch/flow.c | 168 ++++++++++++++++++++++++----------------------- 1 files changed, 86 insertions(+), 82 deletions(-) diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 98c7063..6dfaf60 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c @@ -124,6 +124,7 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies) (offsetof(struct sw_flow_key, field) + \ FIELD_SIZEOF(struct sw_flow_key, field)) +#if IS_ENABLED(CONFIG_IPV6) static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key, int *key_lenp) { @@ -175,6 +176,89 @@ static bool icmp6hdr_ok(struct sk_buff *skb) sizeof(struct icmp6hdr)); } +static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key, + int *key_lenp, int nh_len) +{ + struct icmp6hdr *icmp = icmp6_hdr(skb); + int error = 0; + int key_len; + + /* The ICMPv6 type and code fields use the 16-bit transport port + * fields, so we need to store them in 16-bit network byte order. + */ + key->ipv6.tp.src = htons(icmp->icmp6_type); + key->ipv6.tp.dst = htons(icmp->icmp6_code); + key_len = SW_FLOW_KEY_OFFSET(ipv6.tp); + + if (icmp->icmp6_code == 0 && + (icmp->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION || + icmp->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT)) { + int icmp_len = skb->len - skb_transport_offset(skb); + struct nd_msg *nd; + int offset; + + key_len = SW_FLOW_KEY_OFFSET(ipv6.nd); + + /* In order to process neighbor discovery options, we need the + * entire packet. + */ + if (unlikely(icmp_len < sizeof(*nd))) + goto out; + if (unlikely(skb_linearize(skb))) { + error = -ENOMEM; + goto out; + } + + nd = (struct nd_msg *)skb_transport_header(skb); + key->ipv6.nd.target = nd->target; + key_len = SW_FLOW_KEY_OFFSET(ipv6.nd); + + icmp_len -= sizeof(*nd); + offset = 0; + while (icmp_len >= 8) { + struct nd_opt_hdr *nd_opt = + (struct nd_opt_hdr *)(nd->opt + offset); + int opt_len = nd_opt->nd_opt_len * 8; + + if (unlikely(!opt_len || opt_len > icmp_len)) + goto invalid; + + /* Store the link layer address if the appropriate + * option is provided. It is considered an error if + * the same link layer option is specified twice. + */ + if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LL_ADDR + && opt_len == 8) { + if (unlikely(!is_zero_ether_addr(key->ipv6.nd.sll))) + goto invalid; + memcpy(key->ipv6.nd.sll, + &nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN); + } else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LL_ADDR + && opt_len == 8) { + if (unlikely(!is_zero_ether_addr(key->ipv6.nd.tll))) + goto invalid; + memcpy(key->ipv6.nd.tll, + &nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN); + } + + icmp_len -= opt_len; + offset += opt_len; + } + } + + goto out; + +invalid: + memset(&key->ipv6.nd.target, 0, sizeof(key->ipv6.nd.target)); + memset(key->ipv6.nd.sll, 0, sizeof(key->ipv6.nd.sll)); + memset(key->ipv6.nd.tll, 0, sizeof(key->ipv6.nd.tll)); + +out: + *key_lenp = key_len; + return error; +} +#endif + #define TCP_FLAGS_OFFSET 13 #define TCP_FLAG_MASK 0x3f @@ -487,88 +571,6 @@ static __be16 parse_ethertype(struct sk_buff *skb) return llc->ethertype; } -static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key, - int *key_lenp, int nh_len) -{ - struct icmp6hdr *icmp = icmp6_hdr(skb); - int error = 0; - int key_len; - - /* The ICMPv6 type and code fields use the 16-bit transport port - * fields, so we need to store them in 16-bit network byte order. - */ - key->ipv6.tp.src = htons(icmp->icmp6_type); - key->ipv6.tp.dst = htons(icmp->icmp6_code); - key_len = SW_FLOW_KEY_OFFSET(ipv6.tp); - - if (icmp->icmp6_code == 0 && - (icmp->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION || - icmp->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT)) { - int icmp_len = skb->len - skb_transport_offset(skb); - struct nd_msg *nd; - int offset; - - key_len = SW_FLOW_KEY_OFFSET(ipv6.nd); - - /* In order to process neighbor discovery options, we need the - * entire packet. - */ - if (unlikely(icmp_len < sizeof(*nd))) - goto out; - if (unlikely(skb_linearize(skb))) { - error = -ENOMEM; - goto out; - } - - nd = (struct nd_msg *)skb_transport_header(skb); - key->ipv6.nd.target = nd->target; - key_len = SW_FLOW_KEY_OFFSET(ipv6.nd); - - icmp_len -= sizeof(*nd); - offset = 0; - while (icmp_len >= 8) { - struct nd_opt_hdr *nd_opt = - (struct nd_opt_hdr *)(nd->opt + offset); - int opt_len = nd_opt->nd_opt_len * 8; - - if (unlikely(!opt_len || opt_len > icmp_len)) - goto invalid; - - /* Store the link layer address if the appropriate - * option is provided. It is considered an error if - * the same link layer option is specified twice. - */ - if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LL_ADDR - && opt_len == 8) { - if (unlikely(!is_zero_ether_addr(key->ipv6.nd.sll))) - goto invalid; - memcpy(key->ipv6.nd.sll, - &nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN); - } else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LL_ADDR - && opt_len == 8) { - if (unlikely(!is_zero_ether_addr(key->ipv6.nd.tll))) - goto invalid; - memcpy(key->ipv6.nd.tll, - &nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN); - } - - icmp_len -= opt_len; - offset += opt_len; - } - } - - goto out; - -invalid: - memset(&key->ipv6.nd.target, 0, sizeof(key->ipv6.nd.target)); - memset(key->ipv6.nd.sll, 0, sizeof(key->ipv6.nd.sll)); - memset(key->ipv6.nd.tll, 0, sizeof(key->ipv6.nd.tll)); - -out: - *key_lenp = key_len; - return error; -} - /** * ovs_flow_extract - extracts a flow key from an Ethernet frame. * @skb: sk_buff that contains the frame, with skb->data pointing to the @@ -712,6 +714,7 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key, key_len = SW_FLOW_KEY_OFFSET(ipv4.arp); } } +#if IS_ENABLED(CONFIG_IPV6) } else if (key->eth.type == htons(ETH_P_IPV6)) { int nh_len; /* IPv6 Header + Extensions */ @@ -752,6 +755,7 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key, goto out; } } +#endif } out: -- 1.7.7.6 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev