summaryrefslogtreecommitdiffstats
path: root/src/vnet
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet')
-rw-r--r--src/vnet/ip/ip6.h27
-rw-r--r--src/vnet/ip/ip6_forward.c32
-rw-r--r--src/vnet/ip/ip6_hop_by_hop.h36
3 files changed, 63 insertions, 32 deletions
diff --git a/src/vnet/ip/ip6.h b/src/vnet/ip/ip6.h
index cf40fbb37aa..535f24c05d1 100644
--- a/src/vnet/ip/ip6.h
+++ b/src/vnet/ip/ip6.h
@@ -445,11 +445,30 @@ always_inline u32
ip6_compute_flow_hash (const ip6_header_t * ip,
flow_hash_config_t flow_hash_config)
{
- tcp_header_t *tcp = (void *) (ip + 1);
+ tcp_header_t *tcp;
u64 a, b, c;
u64 t1, t2;
- uword is_tcp_udp = (ip->protocol == IP_PROTOCOL_TCP
- || ip->protocol == IP_PROTOCOL_UDP);
+ uword is_tcp_udp = 0;
+ u8 protocol = ip->protocol;
+
+ if (PREDICT_TRUE
+ ((ip->protocol == IP_PROTOCOL_TCP)
+ || (ip->protocol == IP_PROTOCOL_UDP)))
+ {
+ is_tcp_udp = 1;
+ tcp = (void *) (ip + 1);
+ }
+ else if (ip->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
+ {
+ ip6_hop_by_hop_header_t *hbh = (ip6_hop_by_hop_header_t *) (ip + 1);
+ if ((hbh->protocol == IP_PROTOCOL_TCP) ||
+ (hbh->protocol == IP_PROTOCOL_UDP))
+ {
+ is_tcp_udp = 1;
+ tcp = (tcp_header_t *) ((u8 *) hbh + ((hbh->length + 1) << 3));
+ }
+ protocol = hbh->protocol;
+ }
t1 = (ip->src_address.as_u64[0] ^ ip->src_address.as_u64[1]);
t1 = (flow_hash_config & IP_FLOW_HASH_SRC_ADDR) ? t1 : 0;
@@ -459,7 +478,7 @@ ip6_compute_flow_hash (const ip6_header_t * ip,
a = (flow_hash_config & IP_FLOW_HASH_REVERSE_SRC_DST) ? t2 : t1;
b = (flow_hash_config & IP_FLOW_HASH_REVERSE_SRC_DST) ? t1 : t2;
- b ^= (flow_hash_config & IP_FLOW_HASH_PROTO) ? ip->protocol : 0;
+ b ^= (flow_hash_config & IP_FLOW_HASH_PROTO) ? protocol : 0;
t1 = is_tcp_udp ? tcp->src : 0;
t2 = is_tcp_udp ? tcp->dst : 0;
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index 91a303d4857..b80c757a6d3 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -1161,7 +1161,8 @@ ip6_tcp_udp_icmp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
uword));
}
- /* some icmp packets may come with a "router alert" hop-by-hop extension header (e.g., mldv2 packets) */
+ /* some icmp packets may come with a "router alert" hop-by-hop extension header (e.g., mldv2 packets)
+ * or UDP-Ping packets */
if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS))
{
u32 skip_bytes;
@@ -1169,7 +1170,8 @@ ip6_tcp_udp_icmp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
(ip6_hop_by_hop_ext_t *) data_this_buffer;
/* validate really icmp6 next */
- ASSERT (ext_hdr->next_hdr == IP_PROTOCOL_ICMP6);
+ ASSERT ((ext_hdr->next_hdr == IP_PROTOCOL_ICMP6)
+ || (ext_hdr->next_hdr == IP_PROTOCOL_UDP));
skip_bytes = 8 * (1 + ext_hdr->n_data_u64s);
data_this_buffer = (void *) ((u8 *) data_this_buffer + skip_bytes);
@@ -1317,23 +1319,6 @@ ip6_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
len_diff0 = 0;
len_diff1 = 0;
- /* Skip HBH local processing */
- if (PREDICT_FALSE
- (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS))
- {
- ip6_hop_by_hop_ext_t *ext_hdr =
- (ip6_hop_by_hop_ext_t *) ip6_next_header (ip0);
- next0 = lm->local_next_by_ip_protocol[ext_hdr->next_hdr];
- type0 = lm->builtin_protocol_by_ip_protocol[ext_hdr->next_hdr];
- }
- if (PREDICT_FALSE
- (ip1->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS))
- {
- ip6_hop_by_hop_ext_t *ext_hdr =
- (ip6_hop_by_hop_ext_t *) ip6_next_header (ip1);
- next1 = lm->local_next_by_ip_protocol[ext_hdr->next_hdr];
- type1 = lm->builtin_protocol_by_ip_protocol[ext_hdr->next_hdr];
- }
if (PREDICT_TRUE (IP_PROTOCOL_UDP == ip6_locate_header (p0, ip0,
IP_PROTOCOL_UDP,
&udp_offset0)))
@@ -1458,15 +1443,6 @@ ip6_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
good_l4_checksum0 = (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
len_diff0 = 0;
- /* Skip HBH local processing */
- if (PREDICT_FALSE
- (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS))
- {
- ip6_hop_by_hop_ext_t *ext_hdr =
- (ip6_hop_by_hop_ext_t *) ip6_next_header (ip0);
- next0 = lm->local_next_by_ip_protocol[ext_hdr->next_hdr];
- type0 = lm->builtin_protocol_by_ip_protocol[ext_hdr->next_hdr];
- }
if (PREDICT_TRUE (IP_PROTOCOL_UDP == ip6_locate_header (p0, ip0,
IP_PROTOCOL_UDP,
&udp_offset0)))
diff --git a/src/vnet/ip/ip6_hop_by_hop.h b/src/vnet/ip/ip6_hop_by_hop.h
index 9574f0a5ecc..5f12f647dba 100644
--- a/src/vnet/ip/ip6_hop_by_hop.h
+++ b/src/vnet/ip/ip6_hop_by_hop.h
@@ -230,6 +230,42 @@ ioam_flow_add (u8 encap, u8 * flow_name)
return (index);
}
+always_inline ip6_hop_by_hop_option_t *
+ip6_hbh_get_option (ip6_hop_by_hop_header_t * hbh0, u8 option_to_search)
+{
+ ip6_hop_by_hop_option_t *opt0, *limit0;
+ u8 type0;
+
+ if (!hbh0)
+ return NULL;
+
+ opt0 = (ip6_hop_by_hop_option_t *) (hbh0 + 1);
+ limit0 = (ip6_hop_by_hop_option_t *)
+ ((u8 *) hbh0 + ((hbh0->length + 1) << 3));
+
+ /* Scan the set of h-b-h options, process ones that we understand */
+ while (opt0 < limit0)
+ {
+ type0 = opt0->type;
+ switch (type0)
+ {
+ case 0: /* Pad1 */
+ opt0 = (ip6_hop_by_hop_option_t *) ((u8 *) opt0) + 1;
+ continue;
+ case 1: /* PadN */
+ break;
+ default:
+ if (type0 == option_to_search)
+ return opt0;
+ break;
+ }
+ opt0 =
+ (ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length +
+ sizeof (ip6_hop_by_hop_option_t));
+ }
+ return NULL;
+}
+
#endif /* __included_ip6_hop_by_hop_ioam_h__ */
/*