+ vlib_buffer_advance (b0, -(sizeof (ethernet_header_t)));
+ si0 = vnet_get_sw_interface (vnm, original_sw_if_index);
+ if (si0->type == VNET_SW_INTERFACE_TYPE_SUB)
+ {
+ if (si0->sub.eth.flags.one_tag == 1)
+ {
+ vlib_buffer_advance (b0, -4 /* space for 1 VLAN tag */ );
+ outer_vlan = (si0->sub.eth.outer_vlan_id << 16) | 0x0800;
+ }
+ else if (si0->sub.eth.flags.two_tags == 1)
+ {
+ vlib_buffer_advance (b0, -8 /* space for 2 VLAN tag */ );
+ outer_vlan = (si0->sub.eth.outer_vlan_id << 16) | 0x8100;
+ inner_vlan = (si0->sub.eth.inner_vlan_id << 16) | 0x0800;
+ }
+ }
+
+ mac0 = vlib_buffer_get_current (b0);
+
+ hi0 = vnet_get_sup_hw_interface (vnm, original_sw_if_index);
+ ei0 = pool_elt_at_index (em->interfaces, hi0->hw_instance);
+ clib_memcpy (mac0->src_address, &ei0->address,
+ sizeof (mac0->src_address));
+ clib_memset (mac0->dst_address, 0xff, sizeof (mac0->dst_address));
+
+ if (si0->type == VNET_SW_INTERFACE_TYPE_SUB
+ && outer_vlan != (u32) ~ 0)
+ {
+ mac0->type = (si0->sub.eth.flags.dot1ad == 1) ?
+ clib_net_to_host_u16 (0x88a8) : clib_net_to_host_u16 (0x8100);
+ u32 *vlan_tag = (u32 *) (mac0 + 1);
+ *vlan_tag = clib_host_to_net_u32 (outer_vlan);
+ if (inner_vlan != (u32) ~ 0)
+ {
+ u32 *inner_vlan_tag = (u32 *) (vlan_tag + 1);
+ *inner_vlan_tag = clib_host_to_net_u32 (inner_vlan);
+ }
+ }
+ else
+ {
+ mac0->type = clib_net_to_host_u16 (0x0800);
+ }
+
+ do_trace:
+ if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ dhcp_proxy_trace_t *tr = vlib_add_trace (vm, node,
+ b0, sizeof (*tr));
+ tr->which = 1; /* to client */
+ tr->trace_ip4_address.as_u32 = ia0 ? ia0->as_u32 : 0;
+ tr->error = error0;
+ tr->original_sw_if_index = original_sw_if_index;
+ tr->sw_if_index = sw_if_index;
+ clib_memcpy_fast (tr->packet_data, h0,
+ sizeof (tr->packet_data));
+ }
+
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
+ to_next, n_left_to_next,
+ bi0, next0);