summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuhiro MIKI <nmiki@yahoo-corp.jp>2023-03-29 14:51:16 +0900
committerIlya Maximets <i.maximets@ovn.org>2023-03-29 21:41:28 +0200
commit349112f975ed3a9876d7bde92ba0622d2384f0c4 (patch)
tree553103d06c3822174bcf6d434011eae4927d5371
parent57b9fc50dd2c9fe929a84306994fd9d943dc4246 (diff)
downloadopenvswitch-349112f975ed3a9876d7bde92ba0622d2384f0c4.tar.gz
flow: Support rt_hdr in parse_ipv6_ext_hdrs().
Checks whether IPPROTO_ROUTING exists in the IPv6 extension headers. If it exists, the first address is retrieved. If NULL is specified for "frag_hdr" and/or "rt_hdr", those addresses in the header are not reported to the caller. Of course, "frag_hdr" and "rt_hdr" are properly parsed inside this function. Signed-off-by: Nobuhiro MIKI <nmiki@yahoo-corp.jp> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
-rw-r--r--lib/conntrack.c4
-rw-r--r--lib/flow.c48
-rw-r--r--lib/flow.h3
-rw-r--r--lib/ipf.c15
-rw-r--r--lib/packets.h9
5 files changed, 58 insertions, 21 deletions
diff --git a/lib/conntrack.c b/lib/conntrack.c
index 8cf7779c6..f86fa26f4 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -1617,8 +1617,8 @@ extract_l3_ipv6(struct conn_key *key, const void *data, size_t size,
uint8_t nw_proto = ip6->ip6_nxt;
uint8_t nw_frag = 0;
- const struct ovs_16aligned_ip6_frag *frag_hdr;
- if (!parse_ipv6_ext_hdrs(&data, &size, &nw_proto, &nw_frag, &frag_hdr)) {
+ if (!parse_ipv6_ext_hdrs(&data, &size, &nw_proto, &nw_frag,
+ NULL, NULL)) {
return false;
}
diff --git a/lib/flow.c b/lib/flow.c
index c3a3aa3ce..9501a259e 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -479,9 +479,17 @@ invalid:
static inline bool
parse_ipv6_ext_hdrs__(const void **datap, size_t *sizep, uint8_t *nw_proto,
uint8_t *nw_frag,
- const struct ovs_16aligned_ip6_frag **frag_hdr)
+ const struct ovs_16aligned_ip6_frag **frag_hdr,
+ const struct ip6_rt_hdr **rt_hdr)
{
- *frag_hdr = NULL;
+ if (frag_hdr) {
+ *frag_hdr = NULL;
+ }
+
+ if (rt_hdr) {
+ *rt_hdr = NULL;
+ }
+
while (1) {
if (OVS_LIKELY((*nw_proto != IPPROTO_HOPOPTS)
&& (*nw_proto != IPPROTO_ROUTING)
@@ -504,7 +512,6 @@ parse_ipv6_ext_hdrs__(const void **datap, size_t *sizep, uint8_t *nw_proto,
}
if ((*nw_proto == IPPROTO_HOPOPTS)
- || (*nw_proto == IPPROTO_ROUTING)
|| (*nw_proto == IPPROTO_DSTOPTS)) {
/* These headers, while different, have the fields we care
* about in the same location and with the same
@@ -515,6 +522,18 @@ parse_ipv6_ext_hdrs__(const void **datap, size_t *sizep, uint8_t *nw_proto,
(ext_hdr->ip6e_len + 1) * 8))) {
return false;
}
+ } else if (*nw_proto == IPPROTO_ROUTING) {
+ const struct ip6_rt_hdr *tmp;
+ if (!rt_hdr) {
+ rt_hdr = &tmp;
+ }
+
+ *rt_hdr = *datap;
+ *nw_proto = (*rt_hdr)->nexthdr;
+ if (OVS_UNLIKELY(!data_try_pull(datap, sizep,
+ ((*rt_hdr)->hdrlen + 1) * 8))) {
+ return false;
+ }
} else if (*nw_proto == IPPROTO_AH) {
/* A standard AH definition isn't available, but the fields
* we care about are in the same location as the generic
@@ -527,6 +546,11 @@ parse_ipv6_ext_hdrs__(const void **datap, size_t *sizep, uint8_t *nw_proto,
return false;
}
} else if (*nw_proto == IPPROTO_FRAGMENT) {
+ const struct ovs_16aligned_ip6_frag *tmp;
+ if (!frag_hdr) {
+ frag_hdr = &tmp;
+ }
+
*frag_hdr = *datap;
*nw_proto = (*frag_hdr)->ip6f_nxt;
@@ -561,15 +585,19 @@ parse_ipv6_ext_hdrs__(const void **datap, size_t *sizep, uint8_t *nw_proto,
* has FLOW_NW_FRAG_LATER set. Both first and later fragments have
* FLOW_NW_FRAG_ANY set in 'nw_frag'.
*
+ * If a routing header is found, '*rt_hdr' is set to the routing
+ * header and otherwise set to NULL.
+ *
* A return value of false indicates that there was a problem parsing
* the extension headers.*/
bool
parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto,
uint8_t *nw_frag,
- const struct ovs_16aligned_ip6_frag **frag_hdr)
+ const struct ovs_16aligned_ip6_frag **frag_hdr,
+ const struct ip6_rt_hdr **rt_hdr)
{
return parse_ipv6_ext_hdrs__(datap, sizep, nw_proto, nw_frag,
- frag_hdr);
+ frag_hdr, rt_hdr);
}
bool
@@ -945,9 +973,8 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
nw_ttl = nh->ip6_hlim;
nw_proto = nh->ip6_nxt;
- const struct ovs_16aligned_ip6_frag *frag_hdr;
- if (!parse_ipv6_ext_hdrs__(&data, &size, &nw_proto, &nw_frag,
- &frag_hdr)) {
+ if (!parse_ipv6_ext_hdrs(&data, &size, &nw_proto, &nw_frag,
+ NULL, NULL)) {
goto out;
}
@@ -1200,10 +1227,9 @@ parse_tcp_flags(struct dp_packet *packet,
plen = ntohs(nh->ip6_plen); /* Never pull padding. */
dp_packet_set_l2_pad_size(packet, size - plen);
size = plen;
- const struct ovs_16aligned_ip6_frag *frag_hdr;
nw_proto = nh->ip6_nxt;
- if (!parse_ipv6_ext_hdrs__(&data, &size, &nw_proto, &nw_frag,
- &frag_hdr)) {
+ if (!parse_ipv6_ext_hdrs(&data, &size, &nw_proto, &nw_frag,
+ NULL, NULL)) {
return 0;
}
} else {
diff --git a/lib/flow.h b/lib/flow.h
index c647ad83c..a9d026e1c 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -132,7 +132,8 @@ void packet_expand(struct dp_packet *, const struct flow *, size_t size);
bool parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto,
uint8_t *nw_frag,
- const struct ovs_16aligned_ip6_frag **frag_hdr);
+ const struct ovs_16aligned_ip6_frag **frag_hdr,
+ const struct ip6_rt_hdr **rt_hdr);
bool parse_nsh(const void **datap, size_t *sizep, struct ovs_key_nsh *key);
uint16_t parse_tcp_flags(struct dp_packet *packet, ovs_be16 *dl_type_p,
uint8_t *nw_frag_p, ovs_be16 *first_vlan_tci_p);
diff --git a/lib/ipf.c b/lib/ipf.c
index d45266374..affd440f6 100644
--- a/lib/ipf.c
+++ b/lib/ipf.c
@@ -485,9 +485,9 @@ ipf_reassemble_v6_frags(struct ipf_list *ipf_list)
const void *data = l3 + 1;
size_t datasize = pl;
- const struct ovs_16aligned_ip6_frag *frag_hdr = NULL;
- if (!parse_ipv6_ext_hdrs(&data, &datasize, &nw_proto, &nw_frag, &frag_hdr)
- || !nw_frag || !frag_hdr) {
+ const struct ovs_16aligned_ip6_frag *frag_hdr;
+ if (!parse_ipv6_ext_hdrs(&data, &datasize, &nw_proto, &nw_frag, &frag_hdr,
+ NULL) || !nw_frag || !frag_hdr) {
ipf_print_reass_packet("Unparsed reassembled v6 packet; v6 hdr:", l3);
dp_packet_delete(pkt);
@@ -678,9 +678,9 @@ ipf_is_valid_v6_frag(struct ipf *ipf, struct dp_packet *pkt)
uint8_t nw_proto = l3->ip6_nxt;
const void *data = l3 + 1;
size_t datasize = l3_size - l3_hdr_size;
- const struct ovs_16aligned_ip6_frag *frag_hdr = NULL;
+ const struct ovs_16aligned_ip6_frag *frag_hdr;
if (!parse_ipv6_ext_hdrs(&data, &datasize, &nw_proto, &nw_frag,
- &frag_hdr) || !nw_frag || !frag_hdr) {
+ &frag_hdr, NULL) || !nw_frag || !frag_hdr) {
return false;
}
@@ -721,9 +721,10 @@ ipf_v6_key_extract(struct dp_packet *pkt, ovs_be16 dl_type, uint16_t zone,
uint8_t nw_proto = l3->ip6_nxt;
const void *data = l3 + 1;
size_t datasize = dp_packet_l3_size(pkt) - sizeof *l3;
- const struct ovs_16aligned_ip6_frag *frag_hdr = NULL;
+ const struct ovs_16aligned_ip6_frag *frag_hdr;
- parse_ipv6_ext_hdrs(&data, &datasize, &nw_proto, &nw_frag, &frag_hdr);
+ parse_ipv6_ext_hdrs(&data, &datasize, &nw_proto, &nw_frag, &frag_hdr,
+ NULL);
ovs_assert(nw_frag && frag_hdr);
ovs_be16 ip6f_offlg = frag_hdr->ip6f_offlg;
*start_data_byte = ntohs(ip6f_offlg & IP6F_OFF_MASK) +
diff --git a/lib/packets.h b/lib/packets.h
index 8626aac8d..70cd07222 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -988,6 +988,15 @@ struct ovs_16aligned_ip6_frag {
ovs_16aligned_be32 ip6f_ident;
};
+#define IP6_RT_HDR_LEN 4
+struct ip6_rt_hdr {
+ uint8_t nexthdr;
+ uint8_t hdrlen;
+ uint8_t type;
+ uint8_t segments_left;
+};
+BUILD_ASSERT_DECL(IP6_RT_HDR_LEN == sizeof(struct ip6_rt_hdr));
+
#define ICMP6_HEADER_LEN 4
struct icmp6_header {
uint8_t icmp6_type;