+ u8 l4_proto = 0;
+ u8 l4_hdr_sz = 0;
+
+ gho->outer_l2_hdr_offset = gho->l2_hdr_offset;
+ gho->outer_l3_hdr_offset = gho->l3_hdr_offset;
+ gho->outer_l4_hdr_offset = gho->l4_hdr_offset;
+ gho->outer_l4_hdr_sz = gho->l4_hdr_sz;
+ gho->outer_hdr_sz = gho->hdr_sz;
+
+ gho->l2_hdr_offset = 0;
+ gho->l3_hdr_offset = 0;
+ gho->l4_hdr_offset = 0;
+ gho->l4_hdr_sz = 0;
+ gho->hdr_sz = 0;
+
+ if (gho->gho_flags & GHO_F_IP4)
+ {
+ gho->gho_flags |= GHO_F_OUTER_IP4;
+ }
+ else if (gho->gho_flags & GHO_F_IP6)
+ {
+ gho->gho_flags |= GHO_F_OUTER_IP6;
+ }
+
+ gho->gho_flags &= ~GHO_F_INNER_HDR;
+
+ vnet_get_inner_header (b0, gho);
+
+ gho->l2_hdr_offset = b0->current_data;
+ gho->l3_hdr_offset = 0;
+
+ if (PREDICT_TRUE (gho->gho_flags & GHO_F_IPIP_TUNNEL))
+ {
+ ip4_header_t *ip4 = (ip4_header_t *) vlib_buffer_get_current (b0);
+ gho->l4_hdr_offset = ip4_header_bytes (ip4);
+ l4_proto = ip4->protocol;
+ gho->gho_flags |= GHO_F_IP4;
+ }
+ else if (PREDICT_TRUE (gho->gho_flags & GHO_F_IPIP6_TUNNEL))
+ {
+ ip6_header_t *ip6 = (ip6_header_t *) vlib_buffer_get_current (b0);
+ /* FIXME IPv6 EH traversal */
+ gho->l4_hdr_offset = sizeof (ip6_header_t);
+ l4_proto = ip6->protocol;
+ gho->gho_flags |= GHO_F_IP6;
+ }
+ if (l4_proto == IP_PROTOCOL_TCP)
+ {
+ tcp_header_t *tcp = (tcp_header_t *) (vlib_buffer_get_current (b0) +
+ gho->l4_hdr_offset);
+ l4_hdr_sz = tcp_header_bytes (tcp);
+
+ gho->gho_flags |= GHO_F_TCP;
+
+ }
+ else if (l4_proto == IP_PROTOCOL_UDP)
+ {
+ udp_header_t *udp = (udp_header_t *) (vlib_buffer_get_current (b0) +
+ gho->l4_hdr_offset);
+ l4_hdr_sz = sizeof (*udp);
+
+ gho->gho_flags |= GHO_F_UDP;
+ }
+
+ gho->l4_hdr_sz = l4_hdr_sz;
+ gho->hdr_sz += gho->l4_hdr_offset + l4_hdr_sz;
+
+ vnet_get_outer_header (b0, gho);