FD.io VPP  v18.04-17-g3a0d853
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 
23 
24 #define foreach_pppoe_cp_next \
25 _(DROP, "error-drop") \
26 _(INTERFACE, "interface-output" ) \
27 
28 typedef enum
29 {
30 #define _(s,n) PPPOE_CP_NEXT_##s,
32 #undef _
35 
36 typedef struct {
44 
45 static u8 * format_pppoe_cp_trace (u8 * s, va_list * args)
46 {
47  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
48  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
49  pppoe_cp_trace_t * t = va_arg (*args, pppoe_cp_trace_t *);
50  pppoe_main_t * pem = &pppoe_main;
51 
52  if (t->sw_if_index != pem->cp_if_index)
53  {
54  s = format (s, "PPPoE dispatch from sw_if_index %d next %d error %d \n"
55  " pppoe_code 0x%x ppp_proto 0x%x",
56  t->sw_if_index, t->next_index, t->error,
57  t->pppoe_code, t->ppp_proto);
58  }
59  else
60  {
61  s = format (s, "PPPoE dispatch from cp_if_index %d next %d error %d \n"
62  " pppoe_code 0x%x ppp_proto 0x%x",
63  t->cp_if_index, t->next_index, t->error,
64  t->pppoe_code, t->ppp_proto);
65  }
66  return s;
67 }
68 
69 static uword
71  vlib_node_runtime_t * node,
72  vlib_frame_t * from_frame)
73 {
74  u32 n_left_from, next_index, * from, * to_next;
75  pppoe_main_t * pem = &pppoe_main;
76  vnet_main_t * vnm = pem->vnet_main;
78  u32 pkts_decapsulated = 0;
79  u32 thread_index = vlib_get_thread_index();
80  u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
81  pppoe_entry_key_t cached_key;
82  pppoe_entry_result_t cached_result;
83 
84  from = vlib_frame_vector_args (from_frame);
85  n_left_from = from_frame->n_vectors;
86 
87  /* Clear the one-entry cache in case session table was updated */
88  cached_key.raw = ~0;
89  cached_result.raw = ~0; /* warning be gone */
90 
91  next_index = node->cached_next_index;
92  stats_sw_if_index = node->runtime_data[0];
93  stats_n_packets = stats_n_bytes = 0;
94 
95  while (n_left_from > 0)
96  {
97  u32 n_left_to_next;
98 
99  vlib_get_next_frame (vm, node, next_index,
100  to_next, n_left_to_next);
101 
102  while (n_left_from > 0 && n_left_to_next > 0)
103  {
104  u32 bi0;
105  vlib_buffer_t * b0;
106  ethernet_header_t *h0;
107  pppoe_header_t * pppoe0;
108  pppoe_entry_key_t key0;
109  pppoe_entry_result_t result0;
110 
111  u32 bucket0;
112  u32 next0;
113  u32 error0 = 0;
114  u32 rx_sw_if_index0=~0, tx_sw_if_index0=~0, len0;
117 
118  bi0 = from[0];
119  to_next[0] = bi0;
120  from += 1;
121  to_next += 1;
122  n_left_from -= 1;
123  n_left_to_next -= 1;
124 
125  b0 = vlib_get_buffer (vm, bi0);
126  /* leaves current_data pointing at the pppoe header */
127  pppoe0 = vlib_buffer_get_current (b0);
128  rx_sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
129 
130  if (PREDICT_FALSE (pppoe0->ver_type != PPPOE_VER_TYPE))
131  {
132  error0 = PPPOE_ERROR_BAD_VER_TYPE;
133  next0 = PPPOE_INPUT_NEXT_DROP;
134  goto trace00;
135  }
136 
137  vlib_buffer_reset(b0);
138  h0 = vlib_buffer_get_current (b0);
139 
140  if(rx_sw_if_index0 == pem->cp_if_index)
141  {
142  pppoe_lookup_1 (&pem->link_table, &cached_key, &cached_result,
143  h0->dst_address, 0,
144  &key0, &bucket0, &result0);
145  tx_sw_if_index0 = result0.fields.sw_if_index;
146 
147  if (PREDICT_FALSE (tx_sw_if_index0 == ~0))
148  {
149  error0 = PPPOE_ERROR_NO_SUCH_SESSION;
150  next0 = PPPOE_INPUT_NEXT_DROP;
151  goto trace00;
152  }
153 
154  next0 = PPPOE_CP_NEXT_INTERFACE;
155  vnet_buffer(b0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
156 
157  /* set src mac address */
158  si = vnet_get_sw_interface(vnm, tx_sw_if_index0);
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  .function = pppoe_cp_dispatch,
240  .name = "pppoe-cp-dispatch",
241  /* Takes a vector of packets. */
242  .vector_size = sizeof (u32),
243 
244  .n_next_nodes = PPPOE_CP_N_NEXT,
245  .next_nodes = {
246 #define _(s,n) [PPPOE_CP_NEXT_##s] = n,
248 #undef _
249  },
250 
251  .format_trace = format_pppoe_cp_trace,
252 };
253 
255 
u16 ppp_proto
Definition: pppoe.h:43
vmrglw vmrglh hi
Definition: pppoe.h:112
#define CLIB_UNUSED(x)
Definition: clib.h:79
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:248
pppoe_main_t pppoe_main
Definition: jvpp_pppoe.h:39
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:211
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:464
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
vnet_interface_main_t interface_main
Definition: vnet.h:56
pppoe_cp_next_t
Definition: pppoe_cp_node.c:28
u64 raw
Definition: pppoe.h:146
u8 src_address[6]
Definition: packet.h:56
static uword pppoe_cp_dispatch(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: pppoe_cp_node.c:70
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:419
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:415
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:107
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:718
u8 dst_address[6]
Definition: packet.h:55
u32 cp_if_index
Definition: pppoe.h:169
u64 raw
Definition: pppoe.h:126
#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn)
Definition: node.h:158
vlib_node_registration_t pppoe_cp_dispatch_node
(constructor) VLIB_REGISTER_NODE (pppoe_cp_dispatch_node)
Definition: pppoe_cp_node.c:22
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:209
#define PREDICT_FALSE(x)
Definition: clib.h:105
#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:364
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:130
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1166
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u16 n_vectors
Definition: node.h:344
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:221
vlib_main_t * vm
Definition: buffer.c:294
vlib_node_registration_t pppoe_input_node
(constructor) VLIB_REGISTER_NODE (pppoe_input_node)
Definition: pppoe_decap.c:401
#define clib_memcpy(a, b, c)
Definition: string.h:75
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:454
static u8 * format_pppoe_cp_trace(u8 *s, va_list *args)
Definition: pppoe_cp_node.c:45
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:456
struct pppoe_entry_result_t::@470::@472 fields
unsigned int u32
Definition: types.h:88
vnet_main_t * vnet_main
Definition: pppoe.h:176
Definition: pppoe.h:135
u64 uword
Definition: types.h:112
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
struct _vlib_node_registration vlib_node_registration_t
Definition: defs.h:47
unsigned short u16
Definition: types.h:57
unsigned char u8
Definition: types.h:56
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
#define vnet_buffer(b)
Definition: buffer.h:372
u8 ver_type
Definition: pppoe.h:39
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:111
#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:57
Definition: defs.h:46
#define foreach_pppoe_cp_next
Definition: pppoe_cp_node.c:24