diff options
author | Stanislav Zaikin <zstaseg@gmail.com> | 2020-04-23 12:14:30 +0000 |
---|---|---|
committer | John Lo <loj@cisco.com> | 2020-04-26 13:18:54 +0000 |
commit | e65eea360c394429320a45d695ee4d770673b3d4 (patch) | |
tree | 2b42c9323c85c9e087756fafacfeddaf751874a5 /src/plugins/dhcp | |
parent | 681ea6dd287ed56b4ef32ba831cf9ae7d10c10de (diff) |
dhcp: fix dhcp proxy behavior for qinq and dot1q subinterfaces
Previous behavior worked only when subinterface ID matches with dot1q tag and doesn't work at all in QinQ case.
In this patch I'm checking how subinterface is configured.
Type: fix
Signed-off-by: Stanislav Zaikin <zstaseg@gmail.com>
Change-Id: I7a662a0442fdc8e68aba5d6f469f3b1139a4bc2d
Diffstat (limited to 'src/plugins/dhcp')
-rw-r--r-- | src/plugins/dhcp/dhcp4_proxy_node.c | 36 | ||||
-rw-r--r-- | src/plugins/dhcp/dhcp6_proxy_node.c | 35 |
2 files changed, 57 insertions, 14 deletions
diff --git a/src/plugins/dhcp/dhcp4_proxy_node.c b/src/plugins/dhcp/dhcp4_proxy_node.c index 28c3e624aa1..78c4444a1e8 100644 --- a/src/plugins/dhcp/dhcp4_proxy_node.c +++ b/src/plugins/dhcp/dhcp4_proxy_node.c @@ -532,6 +532,8 @@ dhcp_proxy_to_client_input (vlib_main_t * vm, vnet_hw_interface_t *hi0; u32 sw_if_index = ~0; vnet_sw_interface_t *si0; + u32 inner_vlan = (u32) ~ 0; + u32 outer_vlan = (u32) ~ 0; u32 error0 = (u32) ~ 0; vnet_sw_interface_t *swif; u32 fib_index; @@ -719,7 +721,19 @@ dhcp_proxy_to_client_input (vlib_main_t * vm, 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) - vlib_buffer_advance (b0, -4 /* space for VLAN tag */ ); + { + 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); @@ -728,15 +742,23 @@ dhcp_proxy_to_client_input (vlib_main_t * vm, clib_memcpy (mac0->src_address, ei0->address, sizeof (ei0->address)); clib_memset (mac0->dst_address, 0xff, sizeof (mac0->dst_address)); - mac0->type = (si0->type == VNET_SW_INTERFACE_TYPE_SUB) ? - clib_net_to_host_u16 (0x8100) : clib_net_to_host_u16 (0x0800); - if (si0->type == VNET_SW_INTERFACE_TYPE_SUB) + 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); - u32 tmp; - tmp = (si0->sub.id << 16) | 0x0800; - *vlan_tag = clib_host_to_net_u32 (tmp); + *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: diff --git a/src/plugins/dhcp/dhcp6_proxy_node.c b/src/plugins/dhcp/dhcp6_proxy_node.c index 95e5c9272f5..3231f28b1fd 100644 --- a/src/plugins/dhcp/dhcp6_proxy_node.c +++ b/src/plugins/dhcp/dhcp6_proxy_node.c @@ -595,6 +595,8 @@ dhcpv6_proxy_to_client_input (vlib_main_t * vm, u32 sw_if_index = ~0; u32 original_sw_if_index = ~0; vnet_sw_interface_t *si0; + u32 inner_vlan = (u32) ~ 0; + u32 outer_vlan = (u32) ~ 0; u32 error0 = (u32) ~ 0; vnet_sw_interface_t *swif; dhcpv6_option_t *r0 = 0, *o; @@ -765,7 +767,19 @@ dhcpv6_proxy_to_client_input (vlib_main_t * vm, 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) - vlib_buffer_advance (b0, -4 /* space for VLAN tag */ ); + { + 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) | 0x86dd; + } + 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) | 0x86dd; + } + } mac0 = vlib_buffer_get_current (b0); @@ -773,15 +787,22 @@ dhcpv6_proxy_to_client_input (vlib_main_t * vm, ei0 = pool_elt_at_index (em->interfaces, hi0->hw_instance); clib_memcpy (mac0->src_address, ei0->address, sizeof (ei0->address)); clib_memset (&mac0->dst_address, 0xff, sizeof (mac0->dst_address)); - mac0->type = (si0->type == VNET_SW_INTERFACE_TYPE_SUB) ? - clib_net_to_host_u16 (0x8100) : clib_net_to_host_u16 (0x86dd); - if (si0->type == VNET_SW_INTERFACE_TYPE_SUB) + 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); - u32 tmp; - tmp = (si0->sub.id << 16) | 0x0800; - *vlan_tag = clib_host_to_net_u32 (tmp); + *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 (0x86dd); } /* $$$ consider adding a dynamic next to the graph node, for performance */ |