FD.io VPP  v18.07-rc0-415-g6c78436
Vector Packet Processing
mfib_signal.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 
17 #include <vnet/vnet.h>
18 #include <vnet/mfib/mfib_signal.h>
19 #include <vppinfra/dlist.h>
20 
21 /**
22  * @brief Pool of signals
23  */
25 
26 /**
27  * @brief pool of dlist elements
28  */
30 
31 /**
32  * the list/set of interfaces with signals pending
33  */
34 typedef struct mfib_signal_q_t_
35 {
36  /**
37  * the dlist indext that is the head of the list
38  */
40 
41  /**
42  * Spin lock to protect the list
43  */
44  int mip_lock;
46 
47 /**
48  * @brief The pending queue of signals to deliver to the control plane
49  */
51 
52 static void
54 {
55  dlist_elt_t *head;
56  u32 hi;
57 
58  pool_get(mfib_signal_dlist_pool, head);
59  hi = head - mfib_signal_dlist_pool;
60 
61  mfib_signal_pending.mip_head = hi;
62  clib_dlist_init(mfib_signal_dlist_pool, hi);
63 }
64 
65 void
67 {
69 }
70 
71 static inline void
73 {
74  while (__sync_lock_test_and_set (&mfib_signal_pending.mip_lock, 1))
75  ;
76 }
77 
78 static inline void
80 {
81  mfib_signal_pending.mip_lock = 0;
82 }
83 
84 #define MFIB_SIGNAL_CRITICAL_SECTION(_body) \
85 { \
86  mfib_signal_lock_aquire(); \
87  do { \
88  _body; \
89  } while (0); \
90  mfib_signal_lock_release(); \
91 }
92 
93 int
95  u32 context)
96 {
97  u32 li, si;
98 
99  /*
100  * with the lock held, pop a signal from the q.
101  */
103  ({
104  li = clib_dlist_remove_head(mfib_signal_dlist_pool,
105  mfib_signal_pending.mip_head);
106  }));
107 
108  if (~0 != li)
109  {
110  mfib_signal_t *mfs;
111  mfib_itf_t *mfi;
112  dlist_elt_t *elt;
113 
114  elt = pool_elt_at_index(mfib_signal_dlist_pool, li);
115  si = elt->value;
116 
117  mfs = pool_elt_at_index(mfib_signal_pool, si);
118  mfi = mfib_itf_get(mfs->mfs_itf);
119  mfi->mfi_si = INDEX_INVALID;
120  __sync_fetch_and_and(&mfi->mfi_flags,
122 
123 
124  vl_mfib_signal_send_one(reg, context, mfs);
125 
126  /*
127  * with the lock held, return the resoruces of the signals posted
128  */
130  ({
131  pool_put_index(mfib_signal_pool, si);
132  pool_put_index(mfib_signal_dlist_pool, li);
133  }));
134 
135  return (1);
136  }
137  return (0);
138 }
139 
140 void
142  mfib_itf_t *mfi,
143  vlib_buffer_t *b0)
144 {
145  mfib_signal_t *mfs;
146  dlist_elt_t *elt;
147  u32 si, li;
148 
150  ({
151  pool_get(mfib_signal_pool, mfs);
152  pool_get(mfib_signal_dlist_pool, elt);
153 
154  si = mfs - mfib_signal_pool;
155  li = elt - mfib_signal_dlist_pool;
156 
157  elt->value = si;
158  mfi->mfi_si = li;
159 
160  clib_dlist_addhead(mfib_signal_dlist_pool,
161  mfib_signal_pending.mip_head,
162  li);
163  }));
164 
165  mfs->mfs_entry = mfib_entry_get_index(mfe);
166  mfs->mfs_itf = mfib_itf_get_index(mfi);
167 
168  if (NULL != b0)
169  {
170  mfs->mfs_buffer_len = b0->current_length;
171  memcpy(mfs->mfs_buffer,
175  mfs->mfs_buffer_len));
176  }
177  else
178  {
179  mfs->mfs_buffer_len = 0;
180  }
181 }
182 
183 void
185 {
186  u32 li;
187 
188  /*
189  * lock the queue to prevent further additions while we fiddle.
190  */
191  li = mfi->mfi_si;
192 
193  if (INDEX_INVALID != li)
194  {
195  /*
196  * it's in the pending q
197  */
199  ({
200  dlist_elt_t *elt;
201 
202  /*
203  * with the lock held;
204  * - remove the signal from the pending list
205  * - free up the signal and list entry obejcts
206  */
207  clib_dlist_remove(mfib_signal_dlist_pool, li);
208 
209  elt = pool_elt_at_index(mfib_signal_dlist_pool, li);
210  pool_put_index(mfib_signal_pool, elt->value);
211  pool_put(mfib_signal_dlist_pool, elt);
212  }));
213  }
214 }
vmrglw vmrglh hi
static void clib_dlist_init(dlist_elt_t *pool, u32 index)
Definition: dlist.h:36
void mfib_signal_module_init(void)
Definition: mfib_signal.c:66
A pair of indicies, for the entry and interface resp.
Definition: mfib_signal.h:29
#define NULL
Definition: clib.h:55
An entry in a FIB table.
Definition: mfib_entry.h:31
struct mfib_signal_q_t_ mfib_signal_q_t
the list/set of interfaces with signals pending
static fib_node_index_t mfib_entry_get_index(const mfib_entry_t *mfe)
Definition: mfib_entry.h:158
static void mfib_signal_list_init(void)
Definition: mfib_signal.c:53
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:227
#define MFIB_SIGNAL_CRITICAL_SECTION(_body)
Definition: mfib_signal.c:84
unsigned int u32
Definition: types.h:88
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:461
u32 mip_head
the dlist indext that is the head of the list
Definition: mfib_signal.c:39
static mfib_itf_t * mfib_itf_get(index_t mi)
Get the MFIB interface representation.
Definition: mfib_itf.h:78
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:108
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:202
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:273
#define MFIB_SIGNAL_BUFFER_SIZE
Definition: mfib_signal.h:24
static dlist_elt_t * mfib_signal_dlist_pool
pool of dlist elements
Definition: mfib_signal.c:29
u32 mfi_si
The index of the signal in the pending list.
Definition: mfib_itf.h:45
static void mfib_signal_lock_release(void)
Definition: mfib_signal.c:79
An API client registration, only in vpp/vlib.
Definition: api_common.h:44
static void clib_dlist_addhead(dlist_elt_t *pool, u32 head_index, u32 new_index)
Definition: dlist.h:71
void mfib_signal_remove_itf(const mfib_itf_t *mfi)
Definition: mfib_signal.c:184
mfib_itf_flags_t mfi_flags
Forwarding Flags on the entry - checked in the data-path.
Definition: mfib_itf.h:35
static mfib_signal_t * mfib_signal_pool
Pool of signals.
Definition: mfib_signal.c:24
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:296
int mfib_signal_send_one(struct vl_api_registration_ *reg, u32 context)
Definition: mfib_signal.c:94
index_t mfs_itf
Definition: mfib_signal.h:32
An interface associated with a particular MFIB entry.
Definition: mfib_itf.h:25
static void mfib_signal_lock_aquire(void)
Definition: mfib_signal.c:72
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
Definition: dlist.h:99
int mip_lock
Spin lock to protect the list.
Definition: mfib_signal.c:44
u32 value
Definition: dlist.h:32
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
static mfib_signal_q_t mfib_signal_pending
The pending queue of signals to deliver to the control plane.
Definition: mfib_signal.c:50
void mfib_signal_push(const mfib_entry_t *mfe, mfib_itf_t *mfi, vlib_buffer_t *b0)
Definition: mfib_signal.c:141
u8 mfs_buffer[MFIB_SIGNAL_BUFFER_SIZE]
A buffer copied from the DP plane that triggered the signal.
Definition: mfib_signal.h:37
static index_t mfib_itf_get_index(const mfib_itf_t *mfi)
Definition: mfib_itf.h:84
fib_node_index_t mfs_entry
Definition: mfib_signal.h:31
void vl_mfib_signal_send_one(vl_api_registration_t *reg, u32 context, const mfib_signal_t *mfs)
Definition: ip_api.c:1833
the list/set of interfaces with signals pending
Definition: mfib_signal.c:34
static u32 clib_dlist_remove_head(dlist_elt_t *pool, u32 head_index)
Definition: dlist.h:117