FD.io VPP  v21.01.1
Vector Packet Processing
pppoe_cp_node.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 Intel and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or pemplied.
13  * See the License for the specific language governing permissions and
14  * lpemitations under the License.
15  *------------------------------------------------------------------
16  */
17 
18 #include <vlib/vlib.h>
19 #include <vnet/ppp/packet.h>
20 #include <pppoe/pppoe.h>
21 
22 #define foreach_pppoe_cp_next \
23 _(DROP, "error-drop") \
24 _(INTERFACE, "interface-output" ) \
25 
26 typedef enum
27 {
28 #define _(s,n) PPPOE_CP_NEXT_##s,
30 #undef _
33 
34 typedef struct {
42 
43 static u8 * format_pppoe_cp_trace (u8 * s, va_list * args)
44 {
45  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
46  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
47  pppoe_cp_trace_t * t = va_arg (*args, pppoe_cp_trace_t *);
48  pppoe_main_t * pem = &pppoe_main;
49 
50  if (t->sw_if_index != pem->cp_if_index)
51  {
52  s = format (s, "PPPoE dispatch from sw_if_index %d next %d error %d \n"
53  " pppoe_code 0x%x ppp_proto 0x%x",
54  t->sw_if_index, t->next_index, t->error,
55  t->pppoe_code, t->ppp_proto);
56  }
57  else
58  {
59  s = format (s, "PPPoE dispatch from cp_if_index %d next %d error %d \n"
60  " pppoe_code 0x%x ppp_proto 0x%x",
61  t->cp_if_index, t->next_index, t->error,
62  t->pppoe_code, t->ppp_proto);
63  }
64  return s;
65 }
66 
69  vlib_frame_t * from_frame)
70 {
71  u32 n_left_from, next_index, * from, * to_next;
72  pppoe_main_t * pem = &pppoe_main;
73  vnet_main_t * vnm = pem->vnet_main;
75  u32 pkts_decapsulated = 0;
76  u32 thread_index = vlib_get_thread_index();
77  u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
78  pppoe_entry_key_t cached_key;
79  pppoe_entry_result_t cached_result;
80 
81  from = vlib_frame_vector_args (from_frame);
82  n_left_from = from_frame->n_vectors;
83 
84  /* Clear the one-entry cache in case session table was updated */
85  cached_key.raw = ~0;
86  cached_result.raw = ~0; /* warning be gone */
87 
88  next_index = node->cached_next_index;
89  stats_sw_if_index = node->runtime_data[0];
90  stats_n_packets = stats_n_bytes = 0;
91 
92  while (n_left_from > 0)
93  {
94  u32 n_left_to_next;
95 
96  vlib_get_next_frame (vm, node, next_index,
97  to_next, n_left_to_next);
98 
99  while (n_left_from > 0 && n_left_to_next > 0)
100  {
101  u32 bi0;
102  vlib_buffer_t * b0;
103  ethernet_header_t *h0;
104  pppoe_header_t * pppoe0;
105  pppoe_entry_key_t key0;
106  pppoe_entry_result_t result0;
107 
108  u32 bucket0;
109  u32 next0;
110  u32 error0 = 0;
111  u32 rx_sw_if_index0=~0, tx_sw_if_index0=~0, len0;
114 
115  bi0 = from[0];
116  to_next[0] = bi0;
117  from += 1;
118  to_next += 1;
119  n_left_from -= 1;
120  n_left_to_next -= 1;
121 
122  b0 = vlib_get_buffer (vm, bi0);
123  /* leaves current_data pointing at the pppoe header */
124  pppoe0 = vlib_buffer_get_current (b0);
125  rx_sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
126 
127  if (PREDICT_FALSE (pppoe0->ver_type != PPPOE_VER_TYPE))
128  {
129  error0 = PPPOE_ERROR_BAD_VER_TYPE;
130  next0 = PPPOE_INPUT_NEXT_DROP;
131  goto trace00;
132  }
133 
134  vlib_buffer_reset(b0);
135  h0 = vlib_buffer_get_current (b0);
136 
137  if(rx_sw_if_index0 == pem->cp_if_index)
138  {
139  pppoe_lookup_1 (&pem->link_table, &cached_key, &cached_result,
140  h0->dst_address, 0,
141  &key0, &bucket0, &result0);
142  tx_sw_if_index0 = result0.fields.sw_if_index;
143 
144  if (PREDICT_FALSE (tx_sw_if_index0 == ~0))
145  {
146  error0 = PPPOE_ERROR_NO_SUCH_SESSION;
147  next0 = PPPOE_INPUT_NEXT_DROP;
148  goto trace00;
149  }
150 
151  next0 = PPPOE_CP_NEXT_INTERFACE;
152  vnet_buffer(b0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
153 
154  /* set src mac address */
155  si = vnet_get_sw_interface(vnm, tx_sw_if_index0);
156  if( si->type == VNET_SW_INTERFACE_TYPE_SUB ) {
157  si = vnet_get_sw_interface(vnm, si->sup_sw_if_index);
158  }
159  hi = vnet_get_hw_interface (vnm, si->hw_if_index);
161  }
162  else
163  {
164  pppoe_lookup_1 (&pem->link_table, &cached_key, &cached_result,
165  h0->src_address, 0,
166  &key0, &bucket0, &result0);
167  tx_sw_if_index0 = result0.fields.sw_if_index;
168 
169  /* learn client session */
170  pppoe_learn_process (&pem->link_table, rx_sw_if_index0,
171  &key0, &cached_key,
172  &bucket0, &result0);
173 
174  next0 = PPPOE_CP_NEXT_INTERFACE;
175  vnet_buffer(b0)->sw_if_index[VLIB_TX] = pem->cp_if_index;
176  }
177 
178  len0 = vlib_buffer_length_in_chain (vm, b0);
179 
180  pkts_decapsulated ++;
181  stats_n_packets += 1;
182  stats_n_bytes += len0;
183 
184  /* Batch stats increment on the same pppoe session so counter
185  is not incremented per packet */
186  if (PREDICT_FALSE (rx_sw_if_index0 != stats_sw_if_index))
187  {
188  stats_n_packets -= 1;
189  stats_n_bytes -= len0;
190  if (stats_n_packets)
193  thread_index, stats_sw_if_index,
194  stats_n_packets, stats_n_bytes);
195  stats_n_packets = 1;
196  stats_n_bytes = len0;
197  stats_sw_if_index = rx_sw_if_index0;
198  }
199 
200  trace00:
201  b0->error = error0 ? node->errors[error0] : 0;
202 
203  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
204  {
205  pppoe_cp_trace_t *tr
206  = vlib_add_trace (vm, node, b0, sizeof (*tr));
207  tr->next_index = next0;
208  tr->error = error0;
209  tr->sw_if_index = tx_sw_if_index0;
210  tr->cp_if_index = pem->cp_if_index;
211  tr->pppoe_code = pppoe0->code;
212  tr->ppp_proto = clib_net_to_host_u16(pppoe0->ppp_proto);
213  }
214  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
215  to_next, n_left_to_next,
216  bi0, next0);
217  }
218 
219  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
220  }
221  /* Do we still need this now that session tx stats is kept? */
223  PPPOE_ERROR_DECAPSULATED,
224  pkts_decapsulated);
225 
226  /* Increment any remaining batch stats */
227  if (stats_n_packets)
228  {
231  thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
232  node->runtime_data[0] = stats_sw_if_index;
233  }
234 
235  return from_frame->n_vectors;
236 }
237 
239  .name = "pppoe-cp-dispatch",
240  /* Takes a vector of packets. */
241  .vector_size = sizeof (u32),
242 
243  .n_errors = PPPOE_N_ERROR,
244  .error_strings = pppoe_error_strings,
245 
246  .n_next_nodes = PPPOE_CP_N_NEXT,
247  .next_nodes = {
248 #define _(s,n) [PPPOE_CP_NEXT_##s] = n,
250 #undef _
251  },
252 
253  .format_trace = format_pppoe_cp_trace,
254 };
255 
u16 ppp_proto
Definition: pppoe.h:43
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
Definition: pppoe.h:113
#define CLIB_UNUSED(x)
Definition: clib.h:87
static void vlib_buffer_reset(vlib_buffer_t *b)
Reset current header & length to state they were in when packet was received.
Definition: buffer.h:281
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:239
vnet_interface_main_t interface_main
Definition: vnet.h:65
pppoe_cp_next_t
Definition: pppoe_cp_node.c:26
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
u64 raw
Definition: pppoe.h:147
u8 src_address[6]
Definition: packet.h:56
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
vlib_main_t * vm
Definition: in2out_ed.c:1580
#define VLIB_NODE_FN(node)
Definition: node.h:203
struct pppoe_entry_result_t::@705::@707 fields
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:402
unsigned char u8
Definition: types.h:56
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:882
u8 dst_address[6]
Definition: packet.h:55
description fragment has unexpected format
Definition: map.api:433
unsigned int u32
Definition: types.h:88
u32 cp_if_index
Definition: pppoe.h:170
u64 raw
Definition: pppoe.h:127
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
vlib_node_registration_t pppoe_cp_dispatch_node
(constructor) VLIB_REGISTER_NODE (pppoe_cp_dispatch_node)
unsigned short u16
Definition: types.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:233
#define PREDICT_FALSE(x)
Definition: clib.h:121
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:391
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1231
pppoe_main_t pppoe_main
Definition: pppoe.c:38
static_always_inline void pppoe_learn_process(BVT(clib_bihash) *table, u32 sw_if_index0, pppoe_entry_key_t *key0, pppoe_entry_key_t *cached_key, u32 *bucket0, pppoe_entry_result_t *result0)
Perform learning on one packet based on the mac table lookup result.
Definition: pppoe.h:242
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:170
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:219
vlib_node_registration_t pppoe_input_node
(constructor) VLIB_REGISTER_NODE (pppoe_input_node)
Definition: pppoe_decap.c:470
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:483
static u8 * format_pppoe_cp_trace(u8 *s, va_list *args)
Definition: pppoe_cp_node.c:43
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1580
vnet_main_t * vnet_main
Definition: pppoe.h:177
Definition: pppoe.h:136
vl_api_ip4_address_t hi
Definition: arp.api:37
Definition: defs.h:47
VLIB buffer representation.
Definition: buffer.h:102
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
#define vnet_buffer(b)
Definition: buffer.h:417
vnet_sw_interface_type_t type
Definition: interface.h:737
static_always_inline void pppoe_lookup_1(BVT(clib_bihash) *table, pppoe_entry_key_t *cached_key, pppoe_entry_result_t *cached_result, u8 *mac0, u16 session_id0, pppoe_entry_key_t *key0, u32 *bucket0, pppoe_entry_result_t *result0)
Definition: pppoe.h:277
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:634
u8 si
Definition: lisp_types.api:47
u8 ver_type
Definition: pppoe.h:39
#define PPPOE_VER_TYPE
Definition: pppoe.h:46
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
char * pppoe_error_strings[]
Definition: pppoe_decap.c:462
Definition: defs.h:46
#define foreach_pppoe_cp_next
Definition: pppoe_cp_node.c:22