- Enabling arc "device-input" with the next node "pppoe-input" on the pppoe cp interface: to get rid of L3_MAC_MISMATCH error
- Parsing in the "pppoe-input" node fixed to parse all headers from the scratch
- Getting mac address directly from encap interface when filling up DPO adjacency. Anyway, in the case of the dot1q subinterface, we need to get vlan tags to fill the DPO adjacency.
Type: improvement
Change-Id: I5405931b0f58bef7b852c079a7e66e0da8b5de0f
Signed-off-by: Stanislav Zaikin <zstaseg@gmail.com>
vl_api_mac_address_t client_mac;
};
+/** \brief Create PPPOE control plane interface
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param sw_if_index - software index of the interface
+ @param is_add - to create or to delete
+*/
+define pppoe_add_del_cp
+{
+ u32 client_index;
+ u32 context;
+ vl_api_interface_index_t sw_if_index;
+ u8 is_add;
+ option vat_help = "[ sw_if_index <intfc> is_add <bool> ]";
+};
+
+/** \brief reply for create PPPOE control plane interface
+ @param retval - return code
+*/
+define pppoe_add_del_cp_reply
+{
+ u32 context;
+ i32 retval;
+};
+
/*
* Local Variables:
* eval: (c-set-style "gnu")
u32 sw_if_index,
vnet_link_t link_type, const void *dst_address)
{
- int len = sizeof (pppoe_header_t) + sizeof (ethernet_header_t);
pppoe_main_t *pem = &pppoe_main;
pppoe_session_t *t;
+ vnet_hw_interface_t *hi;
+ vnet_sw_interface_t *si;
+ pppoe_header_t *pppoe;
u32 session_id;
u8 *rw = 0;
session_id = pem->session_index_by_sw_if_index[sw_if_index];
t = pool_elt_at_index (pem->sessions, session_id);
+ int len = sizeof (pppoe_header_t) + sizeof (ethernet_header_t);
+ si = vnet_get_sw_interface (vnm, t->encap_if_index);
+ if (si->type == VNET_SW_INTERFACE_TYPE_SUB)
+ {
+ if (si->sub.eth.flags.one_tag == 1)
+ {
+ len += sizeof (ethernet_vlan_header_t);
+ }
+ }
+
vec_validate_aligned (rw, len - 1, CLIB_CACHE_LINE_BYTES);
ethernet_header_t *eth_hdr = (ethernet_header_t *) rw;
- clib_memcpy (eth_hdr->dst_address, t->client_mac, 6);
- clib_memcpy (eth_hdr->src_address, t->local_mac, 6);
eth_hdr->type = clib_host_to_net_u16 (ETHERNET_TYPE_PPPOE_SESSION);
+ pppoe = (pppoe_header_t *) (eth_hdr + 1);
+
+ if (si->type == VNET_SW_INTERFACE_TYPE_SUB)
+ {
+ if (si->sub.eth.flags.one_tag == 1)
+ {
+ eth_hdr->type = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
+ ethernet_vlan_header_t *vlan =
+ (ethernet_vlan_header_t *) (eth_hdr + 1);
+ vlan->type = clib_host_to_net_u16 (ETHERNET_TYPE_PPPOE_SESSION);
+ vlan->priority_cfi_and_id =
+ clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
+ pppoe = (pppoe_header_t *) (vlan + 1);
+ }
+ si = vnet_get_sw_interface (vnm, si->sup_sw_if_index);
+ }
+
+ // set the right mac addresses
+ hi = vnet_get_hw_interface (vnm, si->hw_if_index);
+ clib_memcpy (eth_hdr->src_address, hi->hw_address, 6);
+ clib_memcpy (eth_hdr->dst_address, t->client_mac, 6);
- pppoe_header_t *pppoe = (pppoe_header_t *) (eth_hdr + 1);
pppoe->ver_type = PPPOE_VER_TYPE;
pppoe->code = 0;
pppoe->session_id = clib_host_to_net_u16 (t->session_id);
pppoe_fixup (vlib_main_t * vm,
const ip_adjacency_t * adj, vlib_buffer_t * b0, const void *data)
{
- const pppoe_session_t *t;
+ //const pppoe_session_t *t;
pppoe_header_t *pppoe0;
+ uword len = (uword) data;
/* update the rewrite string */
- pppoe0 = vlib_buffer_get_current (b0) + sizeof (ethernet_header_t);
+ pppoe0 = vlib_buffer_get_current (b0) + len;
pppoe0->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
- sizeof (pppoe_header_t)
- + sizeof (pppoe0->ppp_proto)
- - sizeof (ethernet_header_t));
- /* Swap to the the packet's output interface to the encap (not the
- * session) interface */
- t = data;
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = t->encap_if_index;
+ + sizeof (pppoe0->ppp_proto) - len);
}
static void
dpo_id_t dpo = DPO_INVALID;
ip_adjacency_t *adj;
pppoe_session_t *t;
+ vnet_sw_interface_t *si;
u32 session_id;
ASSERT (ADJ_INDEX_INVALID != ai);
session_id = pem->session_index_by_sw_if_index[sw_if_index];
t = pool_elt_at_index (pem->sessions, session_id);
+ uword len = sizeof (ethernet_header_t);
+
+ si = vnet_get_sw_interface (vnm, t->encap_if_index);
+ if (si->type == VNET_SW_INTERFACE_TYPE_SUB)
+ {
+ if (si->sub.eth.flags.one_tag == 1)
+ {
+ len += sizeof (ethernet_vlan_header_t);
+ }
+ }
+
switch (adj->lookup_next_index)
{
case IP_LOOKUP_NEXT_ARP:
case IP_LOOKUP_NEXT_GLEAN:
case IP_LOOKUP_NEXT_BCAST:
- adj_nbr_midchain_update_rewrite (ai, pppoe_fixup, t,
+ adj_nbr_midchain_update_rewrite (ai, pppoe_fixup, (void *) len,
ADJ_FLAG_NONE,
pppoe_build_rewrite (vnm,
sw_if_index,
* Construct a partial rewrite from the known ethernet mcast dest MAC
* There's no MAC fixup, so the last 2 parameters are 0
*/
- adj_mcast_midchain_update_rewrite (ai, pppoe_fixup, t,
+ adj_mcast_midchain_update_rewrite (ai, pppoe_fixup, (void *) len,
ADJ_FLAG_NONE,
pppoe_build_rewrite (vnm,
sw_if_index,
u32 cp_if_index;
} vnet_pppoe_add_del_tap_args_t;
+int pppoe_add_del_cp (u32 cp_if_index, u8 is_add);
+
always_inline u64
pppoe_make_key (u8 * mac_address, u16 session_id)
{
}
}
+static void
+vl_api_pppoe_add_del_cp_t_handler (vl_api_pppoe_add_del_cp_t * mp)
+{
+ vl_api_pppoe_add_del_cp_reply_t *rmp;
+ i32 rv = 0;
+ pppoe_main_t *pem = &pppoe_main;
+
+ rv = pppoe_add_del_cp (ntohl (mp->sw_if_index), mp->is_add);
+
+ /* *INDENT-OFF* */
+ REPLY_MACRO(VL_API_PPPOE_ADD_DEL_CP_REPLY);
+ /* *INDENT-ON* */
+}
+
#include <pppoe/pppoe.api.c>
static clib_error_t *
pppoe_api_hookup (vlib_main_t * vm)
#include <pppoe/pppoe.h>
+int
+pppoe_add_del_cp (u32 cp_if_index, u8 is_add)
+{
+ pppoe_main_t *pem = &pppoe_main;
+
+ if (cp_if_index == 0)
+ {
+ return ~0;
+ }
+
+ vnet_feature_enable_disable ("device-input", "pppoe-input",
+ cp_if_index, is_add, 0, 0);
+
+ if (is_add)
+ {
+ pem->cp_if_index = cp_if_index;
+ }
+ else
+ {
+ pem->cp_if_index = ~0;
+ }
+ return 0;
+}
+
static clib_error_t *
pppoe_add_del_cp_command_fn (vlib_main_t * vm,
unformat_input_t * input,
goto done;
}
+ vnet_feature_enable_disable ("device-input", "pppoe-input",
+ cp_if_index, is_add, 0, 0);
+
if (is_add)
{
pem->cp_if_index = cp_if_index;
VLIB_CLI_COMMAND (create_pppoe_cp_cmd, static) =
{
.path = "create pppoe cp",
- .short_help = "create pppoe cp if-name <intfc> [del]",
+ .short_help = "create pppoe cp-if-index <intfc> [del]",
.function = pppoe_add_del_cp_command_fn,
};
/* *INDENT-ON* */
/* set src mac address */
si = vnet_get_sw_interface(vnm, tx_sw_if_index0);
+ if( si->type == VNET_SW_INTERFACE_TYPE_SUB ) {
+ si = vnet_get_sw_interface(vnm, si->sup_sw_if_index);
+ }
hi = vnet_get_hw_interface (vnm, si->hw_if_index);
clib_memcpy_fast (vlib_buffer_get_current (b0)+6, hi->hw_address, 6);
}
vlib_buffer_t * b0, * b1;
u32 next0, next1;
ethernet_header_t *h0, *h1;
+ ethernet_vlan_header_t *vlan0 = 0, *vlan1 = 0;
pppoe_header_t * pppoe0, * pppoe1;
u16 ppp_proto0 = 0, ppp_proto1 = 0;
pppoe_session_t * t0, * t1;
- u32 error0, error1;
+ u32 error0 = 0, error1 = 0;
u32 sw_if_index0, sw_if_index1, len0, len1;
pppoe_entry_key_t key0, key1;
pppoe_entry_result_t result0, result1;
u32 bucket0, bucket1;
+ u16 type0, type1;
/* Prefetch next iteration. */
{
error0 = 0;
error1 = 0;
- /* leaves current_data pointing at the pppoe header */
- pppoe0 = vlib_buffer_get_current (b0);
- pppoe1 = vlib_buffer_get_current (b1);
- ppp_proto0 = clib_net_to_host_u16(pppoe0->ppp_proto);
- ppp_proto1 = clib_net_to_host_u16(pppoe1->ppp_proto);
+ /* get client mac */
+ vlib_buffer_reset(b0);
+ h0 = vlib_buffer_get_current (b0);
+
+ /* get pppoe header */
+ type0 = clib_net_to_host_u16(h0->type);
+ if(type0 == ETHERNET_TYPE_VLAN){
+ vlan0 = (ethernet_vlan_header_t *)(h0+1);
+ type0 = clib_net_to_host_u16(vlan0->type);
+ pppoe0 = (pppoe_header_t*)(vlan0+1);
+ if( type0 != ETHERNET_TYPE_PPPOE_DISCOVERY && type0 != ETHERNET_TYPE_PPPOE_SESSION ) {
+ error0 = PPPOE_ERROR_BAD_VER_TYPE;
+ next0 = PPPOE_INPUT_NEXT_DROP;
+ goto trace0;
+ }
+ } else {
+ pppoe0 = (pppoe_header_t*)(h0+1);
+ }
+
+ ppp_proto0 = clib_net_to_host_u16(pppoe0->ppp_proto);
/* Manipulate packet 0 */
if ((ppp_proto0 != PPP_PROTOCOL_ip4)
&& (ppp_proto0 != PPP_PROTOCOL_ip6))
{
+ vlan0 == 0 ?
+ vlib_buffer_advance(b0, sizeof(*h0))
+ :
+ vlib_buffer_advance(b0, sizeof(*h0)+sizeof(*vlan0));
error0 = PPPOE_ERROR_CONTROL_PLANE;
next0 = PPPOE_INPUT_NEXT_CP_INPUT;
goto trace0;
}
- /* get client mac */
- vlib_buffer_reset(b0);
- h0 = vlib_buffer_get_current (b0);
pppoe_lookup_1 (&pem->session_table, &cached_key, &cached_result,
h0->src_address, pppoe0->session_id,
result0.fields.session_index);
/* Pop Eth and PPPoE header */
- vlib_buffer_advance(b0, sizeof(*h0)+sizeof(*pppoe0));
+ vlan0 == 0 ?
+ vlib_buffer_advance(b0, sizeof(*h0)+sizeof(*pppoe0))
+ :
+ vlib_buffer_advance(b0, sizeof(*h0)+sizeof(*vlan0)+sizeof(*pppoe0));
next0 = (ppp_proto0==PPP_PROTOCOL_ip4)?
PPPOE_INPUT_NEXT_IP4_INPUT
tr->session_id = clib_net_to_host_u32(pppoe0->session_id);
}
+ /* get client mac */
+ vlib_buffer_reset(b1);
+ h1 = vlib_buffer_get_current (b1);
+
+ /* get pppoe header */
+ type1 = clib_net_to_host_u16(h1->type);
+ if(type1 == ETHERNET_TYPE_VLAN){
+ vlan1 = (ethernet_vlan_header_t *)(h1+1);
+ type1 = clib_net_to_host_u16(vlan1->type);
+ pppoe1 = (pppoe_header_t*)(vlan1+1);
+ if( type1 != ETHERNET_TYPE_PPPOE_DISCOVERY && type1 != ETHERNET_TYPE_PPPOE_SESSION ) {
+ error1 = PPPOE_ERROR_BAD_VER_TYPE;
+ next1 = PPPOE_INPUT_NEXT_DROP;
+ goto trace1;
+ }
+ } else {
+ pppoe1 = (pppoe_header_t*)(h1+1);
+ }
+
+ ppp_proto1 = clib_net_to_host_u16(pppoe1->ppp_proto);
/* Manipulate packet 1 */
if ((ppp_proto1 != PPP_PROTOCOL_ip4)
&& (ppp_proto1 != PPP_PROTOCOL_ip6))
{
+ vlan1 == 0 ?
+ vlib_buffer_advance(b1, sizeof(*h1))
+ :
+ vlib_buffer_advance(b1, sizeof(*h1)+sizeof(*vlan1));
error1 = PPPOE_ERROR_CONTROL_PLANE;
next1 = PPPOE_INPUT_NEXT_CP_INPUT;
goto trace1;
}
- /* get client mac */
- vlib_buffer_reset(b1);
- h1 = vlib_buffer_get_current (b1);
-
pppoe_lookup_1 (&pem->session_table, &cached_key, &cached_result,
h1->src_address, pppoe1->session_id,
&key1, &bucket1, &result1);
result1.fields.session_index);
/* Pop Eth and PPPoE header */
- vlib_buffer_advance(b1, sizeof(*h1)+sizeof(*pppoe1));
+ vlan1 == 0 ?
+ vlib_buffer_advance(b1, sizeof(*h1)+sizeof(*pppoe1))
+ :
+ vlib_buffer_advance(b1, sizeof(*h1)+sizeof(*vlan1)+sizeof(*pppoe1));
next1 = (ppp_proto1==PPP_PROTOCOL_ip4)?
PPPOE_INPUT_NEXT_IP4_INPUT
vlib_buffer_t * b0;
u32 next0;
ethernet_header_t *h0;
+ ethernet_vlan_header_t *vlan0 = 0;
pppoe_header_t * pppoe0;
u16 ppp_proto0 = 0;
pppoe_session_t * t0;
pppoe_entry_key_t key0;
pppoe_entry_result_t result0;
u32 bucket0;
+ u32 type0;
bi0 = from[0];
to_next[0] = bi0;
b0 = vlib_get_buffer (vm, bi0);
error0 = 0;
- /* leaves current_data pointing at the pppoe header */
- pppoe0 = vlib_buffer_get_current (b0);
- ppp_proto0 = clib_net_to_host_u16(pppoe0->ppp_proto);
+ /* get client mac */
+ vlib_buffer_reset(b0);
+ h0 = vlib_buffer_get_current (b0);
+
+ /* get pppoe header */
+ type0 = clib_net_to_host_u16(h0->type);
+ if(type0 == ETHERNET_TYPE_VLAN){
+ vlan0 = (ethernet_vlan_header_t *)(h0+1);
+ type0 = clib_net_to_host_u16(vlan0->type);
+ pppoe0 = (pppoe_header_t*)(vlan0+1);
+ if( type0 != ETHERNET_TYPE_PPPOE_DISCOVERY && type0 != ETHERNET_TYPE_PPPOE_SESSION ) {
+ error0 = PPPOE_ERROR_BAD_VER_TYPE;
+ next0 = PPPOE_INPUT_NEXT_DROP;
+ goto trace00;
+ }
+ } else {
+ pppoe0 = (pppoe_header_t*)(h0+1);
+ }
+
+ ppp_proto0 = clib_net_to_host_u16(pppoe0->ppp_proto);
if ((ppp_proto0 != PPP_PROTOCOL_ip4)
&& (ppp_proto0 != PPP_PROTOCOL_ip6))
{
+ vlan0 == 0 ?
+ vlib_buffer_advance(b0, sizeof(*h0))
+ :
+ vlib_buffer_advance(b0, sizeof(*h0)+sizeof(*vlan0));
error0 = PPPOE_ERROR_CONTROL_PLANE;
next0 = PPPOE_INPUT_NEXT_CP_INPUT;
goto trace00;
}
- /* get client mac */
- vlib_buffer_reset(b0);
- h0 = vlib_buffer_get_current (b0);
-
pppoe_lookup_1 (&pem->session_table, &cached_key, &cached_result,
h0->src_address, pppoe0->session_id,
&key0, &bucket0, &result0);
result0.fields.session_index);
/* Pop Eth and PPPoE header */
- vlib_buffer_advance(b0, sizeof(*h0)+sizeof(*pppoe0));
+ vlan0 == 0 ?
+ vlib_buffer_advance(b0, sizeof(*h0)+sizeof(*pppoe0))
+ :
+ vlib_buffer_advance(b0, sizeof(*h0)+sizeof(*vlan0)+sizeof(*pppoe0));
next0 = (ppp_proto0==PPP_PROTOCOL_ip4)?
PPPOE_INPUT_NEXT_IP4_INPUT
.format_trace = format_pppoe_rx_trace,
};
-
+/* *INDENT-OFF* */
+VNET_FEATURE_INIT (pppoe_input_node, static) =
+{
+ .arc_name = "device-input",
+ .node_name = "pppoe-input",
+ .runs_before = VNET_FEATURES ("ethernet-input"),
+};
+/* *INDENT-ON */
return ret;
}
+static void vl_api_pppoe_add_del_cp_reply_t_handler
+ (vl_api_pppoe_add_del_session_reply_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ i32 retval = ntohl (mp->retval);
+ if (vam->async_mode)
+ {
+ vam->async_errors += (retval < 0);
+ }
+ else
+ {
+ vam->retval = retval;
+ vam->result_ready = 1;
+ }
+}
+
+static int
+api_pppoe_add_del_cp (vat_main_t * vam)
+{
+ unformat_input_t *line_input = vam->input;
+ vl_api_pppoe_add_del_cp_t *mp;
+ u8 is_add = 1;
+ u32 sw_if_index = ~0;
+ int ret;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "del"))
+ {
+ is_add = 0;
+ }
+ else if (unformat (line_input, "cp-if-index %d", &sw_if_index))
+ ;
+ }
+
+ M (PPPOE_ADD_DEL_CP, mp);
+
+ mp->is_add = is_add;
+ mp->sw_if_index = sw_if_index;
+
+ S (mp);
+ W (ret);
+ return ret;
+}
+
#include <pppoe/pppoe.api_test.c>