FD.io VPP  v19.08-27-gf4dcae4
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 
68  vlib_node_runtime_t * node,
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  hi = vnet_get_hw_interface (vnm, si->hw_if_index);
158  }
159  else
160  {
161  pppoe_lookup_1 (&pem->link_table, &cached_key, &cached_result,
162  h0->src_address, 0,
163  &key0, &bucket0, &result0);
164  tx_sw_if_index0 = result0.fields.sw_if_index;
165 
166  /* learn client session */
167  pppoe_learn_process (&pem->link_table, rx_sw_if_index0,
168  &key0, &cached_key,
169  &bucket0, &result0);
170 
171  next0 = PPPOE_CP_NEXT_INTERFACE;
172  vnet_buffer(b0)->sw_if_index[VLIB_TX] = pem->cp_if_index;
173  }
174 
175  len0 = vlib_buffer_length_in_chain (vm, b0);
176 
177  pkts_decapsulated ++;
178  stats_n_packets += 1;
179  stats_n_bytes += len0;
180 
181  /* Batch stats increment on the same pppoe session so counter
182  is not incremented per packet */
183  if (PREDICT_FALSE (rx_sw_if_index0 != stats_sw_if_index))
184  {
185  stats_n_packets -= 1;
186  stats_n_bytes -= len0;
187  if (stats_n_packets)
190  thread_index, stats_sw_if_index,
191  stats_n_packets, stats_n_bytes);
192  stats_n_packets = 1;
193  stats_n_bytes = len0;
194  stats_sw_if_index = rx_sw_if_index0;
195  }
196 
197  trace00:
198  b0->error = error0 ? node->errors[error0] : 0;
199 
200  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
201  {
202  pppoe_cp_trace_t *tr
203  = vlib_add_trace (vm, node, b0, sizeof (*tr));
204  tr->next_index = next0;
205  tr->error = error0;
206  tr->sw_if_index = tx_sw_if_index0;
207  tr->cp_if_index = pem->cp_if_index;
208  tr->pppoe_code = pppoe0->code;
209  tr->ppp_proto = clib_net_to_host_u16(pppoe0->ppp_proto);
210  }
211  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
212  to_next, n_left_to_next,
213  bi0, next0);
214  }
215 
216  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
217  }
218  /* Do we still need this now that session tx stats is kept? */
220  PPPOE_ERROR_DECAPSULATED,
221  pkts_decapsulated);
222 
223  /* Increment any remaining batch stats */
224  if (stats_n_packets)
225  {
228  thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
229  node->runtime_data[0] = stats_sw_if_index;
230  }
231 
232  return from_frame->n_vectors;
233 }
234 
236  .name = "pppoe-cp-dispatch",
237  /* Takes a vector of packets. */
238  .vector_size = sizeof (u32),
239 
240  .n_next_nodes = PPPOE_CP_N_NEXT,
241  .next_nodes = {
242 #define _(s,n) [PPPOE_CP_NEXT_##s] = n,
244 #undef _
245  },
246 
247  .format_trace = format_pppoe_cp_trace,
248 };
249 
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
vmrglw vmrglh hi
Definition: pppoe.h:112
#define CLIB_UNUSED(x)
Definition: clib.h:82
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:277
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:220
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:239
struct pppoe_entry_result_t::@593::@595 fields
vnet_interface_main_t interface_main
Definition: vnet.h:56
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:146
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)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
#define VLIB_NODE_FN(node)
Definition: node.h:201
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:366
unsigned char u8
Definition: types.h:56
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:274
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:842
u8 dst_address[6]
Definition: packet.h:55
unsigned int u32
Definition: types.h:88
u32 cp_if_index
Definition: pppoe.h:169
u64 raw
Definition: pppoe.h:126
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:229
#define PREDICT_FALSE(x)
Definition: clib.h:111
#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:218
#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:338
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
pppoe_main_t pppoe_main
Definition: pppoe.c:38
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:213
vlib_main_t * vm
Definition: buffer.c:312
vlib_node_registration_t pppoe_input_node
(constructor) VLIB_REGISTER_NODE (pppoe_input_node)
Definition: pppoe_decap.c:400
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:458
static u8 * format_pppoe_cp_trace(u8 *s, va_list *args)
Definition: pppoe_cp_node.c:43
vnet_main_t * vnet_main
Definition: pppoe.h:176
Definition: pppoe.h:135
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
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:244
#define vnet_buffer(b)
Definition: buffer.h:361
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
Definition: defs.h:46
#define foreach_pppoe_cp_next
Definition: pppoe_cp_node.c:22