summaryrefslogtreecommitdiffstats
path: root/src/plugins/pppoe
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/pppoe')
-rw-r--r--src/plugins/pppoe/pppoe.api24
-rw-r--r--src/plugins/pppoe/pppoe.c66
-rw-r--r--src/plugins/pppoe/pppoe.h2
-rw-r--r--src/plugins/pppoe/pppoe_api.c14
-rw-r--r--src/plugins/pppoe/pppoe_cp.c29
-rw-r--r--src/plugins/pppoe/pppoe_cp_node.c3
-rw-r--r--src/plugins/pppoe/pppoe_decap.c121
-rw-r--r--src/plugins/pppoe/pppoe_test.c45
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>