summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorzstas <zstaseg@gmail.com>2020-05-09 16:57:23 +0000
committerDamjan Marion <dmarion@me.com>2020-10-24 09:53:58 +0000
commit340b10a38ed84600ed3336657ef3a104d9ebe877 (patch)
treef1515e2215be726b6a2d149871fe015b3f550179 /src
parent58d66743aa2a40d73808eee9dcfec77f78d6e9f3 (diff)
pppoe: make pppoe plugin work with dot1q subinterfaces
- 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>
Diffstat (limited to 'src')
-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>