[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <1353080583-14432-1-git-send-email-vyasevic@redhat.com>
Date: Fri, 16 Nov 2012 10:43:03 -0500
From: Vlad Yasevich <vyasevic@...hat.com>
To: netdev@...r.kernel.org
Subject: [PATCH] openvswitch: Make IPv6 packet parsing dependent on IPv6 config
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 <vyasevic@...hat.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
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists