aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStanislav Zaikin <zstaseg@gmail.com>2020-04-23 12:14:30 +0000
committerJohn Lo <loj@cisco.com>2020-04-26 13:18:54 +0000
commite65eea360c394429320a45d695ee4d770673b3d4 (patch)
tree2b42c9323c85c9e087756fafacfeddaf751874a5 /src
parent681ea6dd287ed56b4ef32ba831cf9ae7d10c10de (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')
-rw-r--r--src/plugins/dhcp/dhcp4_proxy_node.c36
-rw-r--r--src/plugins/dhcp/dhcp6_proxy_node.c35
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 */