FD.io VPP  v17.10-9-gd594711
Vector Packet Processing
pppoe_tap_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_tap_next \
25 _(DROP, "error-drop") \
26 _(TUNTAP, "tuntap-tx" ) \
27 _(INTERFACE, "interface-output" ) \
28 
29 typedef enum
30 {
31 #define _(s,n) PPPOE_TAP_NEXT_##s,
33 #undef _
36 
37 typedef struct {
45 
46 static u8 * format_pppoe_tap_trace (u8 * s, va_list * args)
47 {
48  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
49  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
50  pppoe_tap_trace_t * t = va_arg (*args, pppoe_tap_trace_t *);
51  pppoe_main_t * pem = &pppoe_main;
52 
53  if (t->sw_if_index != pem->tap_if_index)
54  {
55  s = format (s, "PPPoE dispatch from sw_if_index %d next %d error %d \n"
56  " pppoe_code 0x%x ppp_proto 0x%x",
57  t->sw_if_index, t->next_index, t->error,
58  t->pppoe_code, t->ppp_proto);
59  }
60  else
61  {
62  s = format (s, "PPPoE dispatch from tap_if_index %d next %d error %d \n"
63  " pppoe_code 0x%x ppp_proto 0x%x",
64  t->tap_if_index, t->next_index, t->error,
65  t->pppoe_code, t->ppp_proto);
66  }
67  return s;
68 }
69 
70 /**
71  * Perform learning on one packet based on the mac table lookup result.
72  * */
75  pppoe_main_t * pem,
76  vlib_buffer_t * b0,
77  u32 sw_if_index0,
78  pppoe_entry_key_t * key0,
79  pppoe_entry_key_t * cached_key,
80  u32 * bucket0,
81  pppoe_entry_result_t * result0)
82 {
83  /* Check mac table lookup result */
84  if (PREDICT_TRUE (result0->fields.sw_if_index == sw_if_index0))
85  {
86  /*
87  * The entry was in the table, and the sw_if_index matched, the normal case
88  */
89  return;
90  }
91  else if (result0->fields.sw_if_index == ~0)
92  {
93  /* The entry was not in table, so add it */
94  result0->fields.sw_if_index = sw_if_index0;
95  result0->fields.session_index = ~0;
96  cached_key->raw = ~0; /* invalidate the cache */
97  }
98  else
99  {
100  /* The entry was in the table, but with the wrong sw_if_index mapping (mac move) */
101  result0->fields.sw_if_index = sw_if_index0;
102  }
103 
104  /* Update the entry */
105  BVT (clib_bihash_kv) kv;
106  kv.key = key0->raw;
107  kv.value = result0->raw;
108  BV (clib_bihash_add_del) (&pem->session_table, &kv, 1 /* is_add */ );
109 }
110 
111 static uword
113  vlib_node_runtime_t * node,
114  vlib_frame_t * from_frame)
115 {
116  u32 n_left_from, next_index, * from, * to_next;
117  pppoe_main_t * pem = &pppoe_main;
118  vnet_main_t * vnm = pem->vnet_main;
120  u32 pkts_decapsulated = 0;
121  u32 thread_index = vlib_get_thread_index();
122  u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
123  pppoe_entry_key_t cached_key;
124  pppoe_entry_result_t cached_result;
125 
126  from = vlib_frame_vector_args (from_frame);
127  n_left_from = from_frame->n_vectors;
128 
129  /* Clear the one-entry cache in case session table was updated */
130  cached_key.raw = ~0;
131  cached_result.raw = ~0; /* warning be gone */
132 
133  next_index = node->cached_next_index;
134  stats_sw_if_index = node->runtime_data[0];
135  stats_n_packets = stats_n_bytes = 0;
136 
137  while (n_left_from > 0)
138  {
139  u32 n_left_to_next;
140 
141  vlib_get_next_frame (vm, node, next_index,
142  to_next, n_left_to_next);
143 
144  while (n_left_from > 0 && n_left_to_next > 0)
145  {
146  u32 bi0;
147  vlib_buffer_t * b0;
148  ethernet_header_t *h0;
149  pppoe_header_t * pppoe0;
150  pppoe_entry_key_t key0;
151  pppoe_entry_result_t result0;
152 
153  u32 bucket0;
154  u32 next0;
155  u32 error0 = 0;
156  u32 rx_sw_if_index0=~0, tx_sw_if_index0=~0, len0;
159 
160  bi0 = from[0];
161  to_next[0] = bi0;
162  from += 1;
163  to_next += 1;
164  n_left_from -= 1;
165  n_left_to_next -= 1;
166 
167  b0 = vlib_get_buffer (vm, bi0);
168  /* leaves current_data pointing at the pppoe header */
169  pppoe0 = vlib_buffer_get_current (b0);
170  rx_sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
171 
172  if (PREDICT_FALSE (pppoe0->ver_type != PPPOE_VER_TYPE))
173  {
174  error0 = PPPOE_ERROR_BAD_VER_TYPE;
175  next0 = PPPOE_INPUT_NEXT_DROP;
176  goto trace00;
177  }
178 
179  vlib_buffer_reset(b0);
180  h0 = vlib_buffer_get_current (b0);
181 
182  if(rx_sw_if_index0 == pem->tap_if_index)
183  {
184  pppoe_lookup_1 (&pem->session_table, &cached_key, &cached_result,
185  h0->dst_address, 0,
186  &key0, &bucket0, &result0);
187  tx_sw_if_index0 = result0.fields.sw_if_index;
188 
189  if (PREDICT_FALSE (tx_sw_if_index0 == ~0))
190  {
191  error0 = PPPOE_ERROR_NO_SUCH_SESSION;
192  next0 = PPPOE_INPUT_NEXT_DROP;
193  goto trace00;
194  }
195 
196  next0 = PPPOE_TAP_NEXT_INTERFACE;
197  vnet_buffer(b0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
198 
199  /* set src mac address */
200  si = vnet_get_sw_interface(vnm, tx_sw_if_index0);
201  hi = vnet_get_hw_interface (vnm, si->hw_if_index);
203  }
204  else
205  {
206  pppoe_lookup_1 (&pem->session_table, &cached_key, &cached_result,
207  h0->src_address, pppoe0->session_id,
208  &key0, &bucket0, &result0);
209  tx_sw_if_index0 = result0.fields.sw_if_index;
210 
211  /* learn client session */
212  pppoe_learn_process (node, pem, b0, rx_sw_if_index0,
213  &key0, &cached_key,
214  &bucket0, &result0);
215 
216  next0 = PPPOE_TAP_NEXT_TUNTAP;
217  vnet_buffer(b0)->sw_if_index[VLIB_TX] = pem->tap_if_index;
218  }
219 
220  len0 = vlib_buffer_length_in_chain (vm, b0);
221 
222  pkts_decapsulated ++;
223  stats_n_packets += 1;
224  stats_n_bytes += len0;
225 
226  /* Batch stats increment on the same pppoe session so counter
227  is not incremented per packet */
228  if (PREDICT_FALSE (rx_sw_if_index0 != stats_sw_if_index))
229  {
230  stats_n_packets -= 1;
231  stats_n_bytes -= len0;
232  if (stats_n_packets)
235  thread_index, stats_sw_if_index,
236  stats_n_packets, stats_n_bytes);
237  stats_n_packets = 1;
238  stats_n_bytes = len0;
239  stats_sw_if_index = rx_sw_if_index0;
240  }
241 
242  trace00:
243  b0->error = error0 ? node->errors[error0] : 0;
244 
246  {
248  = vlib_add_trace (vm, node, b0, sizeof (*tr));
249  tr->next_index = next0;
250  tr->error = error0;
251  tr->sw_if_index = tx_sw_if_index0;
252  tr->tap_if_index = pem->tap_if_index;
253  tr->pppoe_code = pppoe0->code;
254  tr->ppp_proto = clib_net_to_host_u16(pppoe0->ppp_proto);
255  }
256  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
257  to_next, n_left_to_next,
258  bi0, next0);
259  }
260 
261  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
262  }
263  /* Do we still need this now that session tx stats is kept? */
265  PPPOE_ERROR_DECAPSULATED,
266  pkts_decapsulated);
267 
268  /* Increment any remaining batch stats */
269  if (stats_n_packets)
270  {
273  thread_index, stats_sw_if_index, stats_n_packets, stats_n_bytes);
274  node->runtime_data[0] = stats_sw_if_index;
275  }
276 
277  return from_frame->n_vectors;
278 }
279 
281  .function = pppoe_tap_dispatch,
282  .name = "pppoe-tap-dispatch",
283  /* Takes a vector of packets. */
284  .vector_size = sizeof (u32),
285 
286  .n_next_nodes = PPPOE_TAP_N_NEXT,
287  .next_nodes = {
288 #define _(s,n) [PPPOE_TAP_NEXT_##s] = n,
290 #undef _
291  },
292 
293  .format_trace = format_pppoe_tap_trace,
294 };
295 
297 
static uword pppoe_tap_dispatch(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
u16 ppp_proto
Definition: pppoe.h:43
static_always_inline void pppoe_learn_process(vlib_node_runtime_t *node, pppoe_main_t *pem, vlib_buffer_t *b0, 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.
vmrglw vmrglh hi
Definition: pppoe.h:109
#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:232
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
vnet_interface_main_t interface_main
Definition: vnet.h:56
#define PREDICT_TRUE(x)
Definition: clib.h:98
u64 raw
Definition: pppoe.h:143
u32 tap_if_index
Definition: pppoe.h:163
u8 src_address[6]
Definition: packet.h:54
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
struct pppoe_entry_result_t::@367::@369 fields
struct _vlib_node_registration vlib_node_registration_t
static_always_inline void pppoe_lookup_1(BVT(clib_bihash)*session_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:230
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
pppoe_tap_next_t
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 u8 * format_pppoe_tap_trace(u8 *s, va_list *args)
#define foreach_pppoe_tap_next
#define static_always_inline
Definition: clib.h:85
int clib_bihash_add_del(clib_bihash *h, clib_bihash_kv *add_v, int is_add)
Add or delete a (key,value) pair from a bi-hash table.
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:668
u8 dst_address[6]
Definition: packet.h:53
static BVT(clib_bihash)
Definition: adj_nbr.c:26
u64 raw
Definition: pppoe.h:123
u16 session_id
Definition: pppoe.h:41
vlib_node_registration_t pppoe_tap_dispatch_node
(constructor) VLIB_REGISTER_NODE (pppoe_tap_dispatch_node)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:193
#define PREDICT_FALSE(x)
Definition: clib.h:97
#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:216
#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:113
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1158
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:283
vlib_node_registration_t pppoe_input_node
(constructor) VLIB_REGISTER_NODE (pppoe_input_node)
Definition: pppoe_decap.c:401
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
#define clib_memcpy(a, b, c)
Definition: string.h:69
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
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:456
unsigned int u32
Definition: types.h:88
vnet_main_t * vnet_main
Definition: pppoe.h:170
Definition: pppoe.h:132
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
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:306
#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn)
Definition: node.h:158
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
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:75
#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