diff options
Diffstat (limited to 'src/plugins/pppoe')
-rw-r--r-- | src/plugins/pppoe/pppoe.api | 24 | ||||
-rw-r--r-- | src/plugins/pppoe/pppoe.c | 66 | ||||
-rw-r--r-- | src/plugins/pppoe/pppoe.h | 2 | ||||
-rw-r--r-- | src/plugins/pppoe/pppoe_api.c | 14 | ||||
-rw-r--r-- | src/plugins/pppoe/pppoe_cp.c | 29 | ||||
-rw-r--r-- | src/plugins/pppoe/pppoe_cp_node.c | 3 | ||||
-rw-r--r-- | src/plugins/pppoe/pppoe_decap.c | 121 | ||||
-rw-r--r-- | src/plugins/pppoe/pppoe_test.c | 45 |
8 files changed, 265 insertions, 39 deletions
diff --git a/src/plugins/pppoe/pppoe.api b/src/plugins/pppoe/pppoe.api index fcbbf8a2f97..01f4ba4375d 100644 --- a/src/plugins/pppoe/pppoe.api +++ b/src/plugins/pppoe/pppoe.api @@ -86,6 +86,30 @@ define pppoe_session_details 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") diff --git a/src/plugins/pppoe/pppoe.c b/src/plugins/pppoe/pppoe.c index 46faa1f33eb..5ad82694ac1 100644 --- a/src/plugins/pppoe/pppoe.c +++ b/src/plugins/pppoe/pppoe.c @@ -98,23 +98,53 @@ pppoe_build_rewrite (vnet_main_t * vnm, 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); @@ -142,20 +172,16 @@ static void 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 @@ -165,6 +191,7 @@ pppoe_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai) 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); @@ -173,12 +200,23 @@ pppoe_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t 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, @@ -190,7 +228,7 @@ pppoe_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai) * 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, diff --git a/src/plugins/pppoe/pppoe.h b/src/plugins/pppoe/pppoe.h index 3e331ee6a11..a72b7349328 100644 --- a/src/plugins/pppoe/pppoe.h +++ b/src/plugins/pppoe/pppoe.h @@ -205,6 +205,8 @@ typedef struct 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) { diff --git a/src/plugins/pppoe/pppoe_api.c b/src/plugins/pppoe/pppoe_api.c index ca9223779de..6da66c8f9f1 100644 --- a/src/plugins/pppoe/pppoe_api.c +++ b/src/plugins/pppoe/pppoe_api.c @@ -139,6 +139,20 @@ vl_api_pppoe_session_dump_t_handler (vl_api_pppoe_session_dump_t * mp) } } +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) diff --git a/src/plugins/pppoe/pppoe_cp.c b/src/plugins/pppoe/pppoe_cp.c index b99bf79679d..6c6ba249fcc 100644 --- a/src/plugins/pppoe/pppoe_cp.c +++ b/src/plugins/pppoe/pppoe_cp.c @@ -17,6 +17,30 @@ #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, @@ -55,6 +79,9 @@ pppoe_add_del_cp_command_fn (vlib_main_t * vm, 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; @@ -74,7 +101,7 @@ done: 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* */ diff --git a/src/plugins/pppoe/pppoe_cp_node.c b/src/plugins/pppoe/pppoe_cp_node.c index bf9018e8c90..1a44b5d3853 100644 --- a/src/plugins/pppoe/pppoe_cp_node.c +++ b/src/plugins/pppoe/pppoe_cp_node.c @@ -153,6 +153,9 @@ VLIB_NODE_FN (pppoe_cp_dispatch_node) (vlib_main_t * vm, /* 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); } diff --git a/src/plugins/pppoe/pppoe_decap.c b/src/plugins/pppoe/pppoe_decap.c index 1079cc82850..b2a6e4a396e 100644 --- a/src/plugins/pppoe/pppoe_decap.c +++ b/src/plugins/pppoe/pppoe_decap.c @@ -82,14 +82,16 @@ VLIB_NODE_FN (pppoe_input_node) (vlib_main_t * vm, 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. */ { @@ -119,24 +121,40 @@ VLIB_NODE_FN (pppoe_input_node) (vlib_main_t * vm, 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, @@ -152,7 +170,10 @@ VLIB_NODE_FN (pppoe_input_node) (vlib_main_t * vm, 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 @@ -194,20 +215,40 @@ VLIB_NODE_FN (pppoe_input_node) (vlib_main_t * vm, 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); @@ -222,7 +263,10 @@ VLIB_NODE_FN (pppoe_input_node) (vlib_main_t * vm, 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 @@ -275,6 +319,7 @@ VLIB_NODE_FN (pppoe_input_node) (vlib_main_t * vm, 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; @@ -283,6 +328,7 @@ VLIB_NODE_FN (pppoe_input_node) (vlib_main_t * vm, pppoe_entry_key_t key0; pppoe_entry_result_t result0; u32 bucket0; + u32 type0; bi0 = from[0]; to_next[0] = bi0; @@ -294,22 +340,39 @@ VLIB_NODE_FN (pppoe_input_node) (vlib_main_t * vm, 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); @@ -324,7 +387,10 @@ VLIB_NODE_FN (pppoe_input_node) (vlib_main_t * vm, 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 @@ -416,4 +482,11 @@ VLIB_REGISTER_NODE (pppoe_input_node) = { .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 */ diff --git a/src/plugins/pppoe/pppoe_test.c b/src/plugins/pppoe/pppoe_test.c index d66eab1ba63..b2daadba896 100644 --- a/src/plugins/pppoe/pppoe_test.c +++ b/src/plugins/pppoe/pppoe_test.c @@ -237,4 +237,49 @@ api_pppoe_session_dump (vat_main_t * vam) 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> |