FD.io VPP  v21.06-3-gbb25fbf28
Vector Packet Processing
ip_interface.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 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 #include <vnet/ip/ip.h>
17 
18 /**
19  * @file
20  * @brief IP prefix management on interfaces
21  */
22 
23 u32
25  void *addr_fib, u32 address_length)
26 {
27  uword *p = mhash_get (&lm->address_to_if_address_index, addr_fib);
28 
29  if (p)
30  return (p[0]);
31 
32  return (~0);
33 }
34 
38  void *addr_fib,
39  u32 address_length, u32 * result_if_address_index)
40 {
41  vnet_main_t *vnm = vnet_get_main ();
42  ip_interface_address_t *a, *prev;
43  u32 pi; /* previous index */
44  u32 ai;
45  u32 hi; /* head index */
46 
47  /* Verify given length. */
48  if ((address_length == 0) ||
49  (lm->is_ip6 && address_length > 128) ||
50  (!lm->is_ip6 && address_length > 32))
51  {
52  vnm->api_errno = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
53  return clib_error_create
54  ("%U wrong length for interface %U",
55  lm->format_address_and_length, addr_fib,
56  address_length, format_vnet_sw_if_index_name, vnm, sw_if_index);
57  }
58 
60  sw_if_index, ~0);
61 
63 
64  ai = a - lm->if_address_pool;
66 
67  prev = 0;
68  while (pi != (u32) ~ 0)
69  {
70  prev = pool_elt_at_index (lm->if_address_pool, pi);
71  pi = prev->next_this_sw_interface;
72  }
73  pi = prev ? prev - lm->if_address_pool : (u32) ~ 0;
74 
75  a->address_key = mhash_set (&lm->address_to_if_address_index,
76  addr_fib, ai, /* old_value */ 0);
77  a->address_length = address_length;
78  a->sw_if_index = sw_if_index;
79  a->flags = 0;
80  a->prev_this_sw_interface = pi;
81  a->next_this_sw_interface = ~0;
82  if (prev)
83  prev->next_this_sw_interface = ai;
84 
86  (hi != ~0) ? hi : ai;
87 
88  *result_if_address_index = ai;
89 
90  return (NULL);
91 }
92 
95  vnet_main_t * vnm,
96  u32 address_index, void *addr_fib,
97  u32 address_length, u32 sw_if_index)
98 {
99  ip_interface_address_t *a, *prev, *next;
100 
101  a = pool_elt_at_index (lm->if_address_pool, address_index);
102 
103  if (a->sw_if_index != sw_if_index)
104  {
105  vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE;
106  return clib_error_create ("%U not found for interface %U",
108  addr_fib, address_length,
111  }
112 
113  if (a->prev_this_sw_interface != ~0)
114  {
116  a->prev_this_sw_interface);
117  prev->next_this_sw_interface = a->next_this_sw_interface;
118  }
119  if (a->next_this_sw_interface != ~0)
120  {
122  a->next_this_sw_interface);
123  next->prev_this_sw_interface = a->prev_this_sw_interface;
124 
125  if (a->prev_this_sw_interface == ~0)
126  lm->if_address_pool_index_by_sw_if_index[a->sw_if_index] =
127  a->next_this_sw_interface;
128  }
129 
130  if ((a->next_this_sw_interface == ~0) && (a->prev_this_sw_interface == ~0))
131  lm->if_address_pool_index_by_sw_if_index[a->sw_if_index] = ~0;
132 
134  /* old_value */ 0);
135  pool_put (lm->if_address_pool, a);
136  return NULL;
137 }
138 
139 u8
140 ip_interface_has_address (u32 sw_if_index, ip46_address_t * ip, u8 is_ip4)
141 {
142  ip_interface_address_t *ia = 0;
143 
144  if (is_ip4)
145  {
148  /* *INDENT-OFF* */
149  foreach_ip_interface_address (lm4, ia, sw_if_index, 1 /* unnumbered */ ,
150  ({
152  if (ip4_address_compare (ip4, &ip->ip4) == 0)
153  return 1;
154  }));
155  /* *INDENT-ON* */
156  }
157  else
158  {
160  ip6_address_t *ip6;
161  /* *INDENT-OFF* */
162  foreach_ip_interface_address (lm6, ia, sw_if_index, 1 /* unnumbered */ ,
163  ({
165  if (ip6_address_compare (ip6, &ip->ip6) == 0)
166  return 1;
167  }));
168  /* *INDENT-ON* */
169  }
170  return 0;
171 }
172 
173 void *
175 {
178  ip_interface_address_t *ia = 0;
179 
180  if (is_ip4)
181  {
182  /* *INDENT-OFF* */
183  foreach_ip_interface_address (lm4, ia, sw_if_index, 1 /* unnumbered */ ,
184  ({
185  return ip_interface_address_get_address (lm4, ia);
186  }));
187  /* *INDENT-ON* */
188  }
189  else
190  {
191  /* *INDENT-OFF* */
192  foreach_ip_interface_address (lm6, ia, sw_if_index, 1 /* unnumbered */ ,
193  ({
194  ip6_address_t *rv;
196  /* Trying to use a link-local ip6 src address is a fool's errand */
198  return rv;
199  }));
200  /* *INDENT-ON* */
201  }
202 
203  return 0;
204 }
205 
206 static walk_rc_t
208  vnet_sw_interface_t * si, void *ctx)
209 {
212  ip_interface_address_t *ia = 0;
213 
214  /* *INDENT-OFF* */
215  foreach_ip_interface_address (lm4, ia, si->sw_if_index, 1 /* unnumbered */ ,
216  ({
217  ia->flags |= IP_INTERFACE_ADDRESS_FLAG_STALE;
218  }));
219  foreach_ip_interface_address (lm6, ia, si->sw_if_index, 1 /* unnumbered */ ,
220  ({
221  ia->flags |= IP_INTERFACE_ADDRESS_FLAG_STALE;
222  }));
223  /* *INDENT-ON* */
224 
225  return (WALK_CONTINUE);
226 }
227 
228 void
230 {
233 }
234 
235 static walk_rc_t
237  vnet_sw_interface_t * si, void *ctx)
238 {
240  ip4_address_t *ip4_addrs = 0;
241  ip6_address_t *ip6_addrs = 0;
242  ip4_main_t *im4 = &ip4_main;
243  ip6_main_t *im6 = &ip6_main;
245  u32 *ip6_masks = 0;
246  u32 *ip4_masks = 0;
247  int i;
248 
249  /* *INDENT-OFF* */
251  ({
252  if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE)
253  {
254  ip4_address_t * x = (ip4_address_t *)
255  ip_interface_address_get_address (&im4->lookup_main, ia);
256  vec_add1 (ip4_addrs, x[0]);
257  vec_add1 (ip4_masks, ia->address_length);
258  }
259  }));
260 
261  foreach_ip_interface_address (&im6->lookup_main, ia, si->sw_if_index, 1,
262  ({
263  if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE)
264  {
265  ip6_address_t * x = (ip6_address_t *)
266  ip_interface_address_get_address (&im6->lookup_main, ia);
267  vec_add1 (ip6_addrs, x[0]);
268  vec_add1 (ip6_masks, ia->address_length);
269  }
270  }));
271  /* *INDENT-ON* */
272 
273  for (i = 0; i < vec_len (ip4_addrs); i++)
275  ip4_masks[i], 1 /* is_del */ );
276  for (i = 0; i < vec_len (ip6_addrs); i++)
278  ip6_masks[i], 1 /* is_del */ );
279 
280  vec_free (ip4_addrs);
281  vec_free (ip4_masks);
282  vec_free (ip6_addrs);
283  vec_free (ip6_masks);
284 
285  return (WALK_CONTINUE);
286 }
287 
288 void
290 {
293 }
294 
295 /*
296  * fd.io coding-style-patch-verification: ON
297  *
298  * Local Variables:
299  * eval: (c-set-style "gnu")
300  * End:
301  */
ip6_address_is_link_local_unicast
static uword ip6_address_is_link_local_unicast(const ip6_address_t *a)
Definition: ip6_packet.h:253
ip_interface_address_get_address
static void * ip_interface_address_get_address(ip_lookup_main_t *lm, ip_interface_address_t *a)
Definition: ip_interface.h:43
ip_lookup_main_t::is_ip6
u32 is_ip6
1 for ip6; 0 for ip4.
Definition: lookup.h:152
foreach_ip_interface_address
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
Definition: ip_interface.h:57
vnet_sw_interface_t
Definition: interface.h:868
WALK_CONTINUE
@ WALK_CONTINUE
Definition: interface_funcs.h:174
ip4_main_t::lookup_main
ip_lookup_main_t lookup_main
Definition: ip4.h:109
ip4
vl_api_ip4_address_t ip4
Definition: one.api:376
ip4_main
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1105
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
ip6_address_compare
int ip6_address_compare(ip6_address_t *a1, ip6_address_t *a2)
Definition: ip46_cli.c:60
ip_interface_address_sweep_one_interface
static walk_rc_t ip_interface_address_sweep_one_interface(vnet_main_t *vnm, vnet_sw_interface_t *si, void *ctx)
Definition: ip_interface.c:236
next
u16 * next
Definition: nat44_ei_out2in.c:718
pool_put
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
mhash_get
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
hi
vl_api_ip4_address_t hi
Definition: arp.api:37
ip_interface_address_mark_one_interface
static walk_rc_t ip_interface_address_mark_one_interface(vnet_main_t *vnm, vnet_sw_interface_t *si, void *ctx)
Definition: ip_interface.c:207
ip_interface_address_add
clib_error_t * ip_interface_address_add(ip_lookup_main_t *lm, u32 sw_if_index, void *addr_fib, u32 address_length, u32 *result_if_address_index)
Definition: ip_interface.c:36
vnet_sw_interface_t::sw_if_index
u32 sw_if_index
Definition: interface.h:875
ip_lookup_main_t::if_address_pool_index_by_sw_if_index
u32 * if_address_pool_index_by_sw_if_index
Head of doubly linked list of interface addresses for each software interface.
Definition: lookup.h:131
ip_interface_address_mark
void ip_interface_address_mark(void)
Definition: ip_interface.c:229
ip_interface_get_first_ip
void * ip_interface_get_first_ip(u32 sw_if_index, u8 is_ip4)
Definition: ip_interface.c:174
clib_error_create
#define clib_error_create(args...)
Definition: error.h:96
ip6_add_del_interface_address
clib_error_t * ip6_add_del_interface_address(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *address, u32 address_length, u32 is_del)
Definition: ip6_forward.c:297
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
ip4_add_del_interface_address
clib_error_t * ip4_add_del_interface_address(vlib_main_t *vm, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 is_del)
Definition: ip4_forward.c:833
ip_lookup_main_t::address_to_if_address_index
mhash_t address_to_if_address_index
Hash table mapping address to index in interface address pool.
Definition: lookup.h:127
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
uword
u64 uword
Definition: types.h:112
i
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
ip4_address_t
Definition: ip4_packet.h:50
ip4_address_compare
int ip4_address_compare(ip4_address_t *a1, ip4_address_t *a2)
Definition: ip46_cli.c:53
vnet_main_t::api_errno
vnet_api_error_t api_errno
Definition: vnet.h:109
ip6_main
ip6_main_t ip6_main
Definition: ip6_forward.c:2787
vnet_main_t
Definition: vnet.h:76
vec_free
#define vec_free(V)
Free vector's memory (no header).
Definition: vec.h:395
format_vnet_sw_if_index_name
format_function_t format_vnet_sw_if_index_name
Definition: interface_funcs.h:455
vec_validate_init_empty
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header,...
Definition: vec.h:570
ip.h
u32
unsigned int u32
Definition: types.h:88
ip_interface_address_sweep
void ip_interface_address_sweep(void)
Definition: ip_interface.c:289
ip6
vl_api_ip6_address_t ip6
Definition: one.api:424
ctx
long ctx[MAX_CONNS]
Definition: main.c:144
si
vnet_sw_interface_t * si
Definition: interface_output.c:398
ip6_main_t::lookup_main
ip_lookup_main_t lookup_main
Definition: ip6.h:112
ip_interface_has_address
u8 ip_interface_has_address(u32 sw_if_index, ip46_address_t *ip, u8 is_ip4)
Definition: ip_interface.c:140
ip6_main_t
Definition: ip6.h:110
ip_lookup_main_t
Definition: lookup.h:121
ip_lookup_main_t::if_address_pool
ip_interface_address_t * if_address_pool
Pool of addresses that are assigned to interfaces.
Definition: lookup.h:124
vlib_main_t
Definition: main.h:102
ip_interface_address_del
clib_error_t * ip_interface_address_del(ip_lookup_main_t *lm, vnet_main_t *vnm, u32 address_index, void *addr_fib, u32 address_length, u32 sw_if_index)
Definition: ip_interface.c:94
vlib_get_main
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
pool_get_zero
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:258
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
a
a
Definition: bitmap.h:544
ip_lookup_main_t::format_address_and_length
format_function_t * format_address_and_length
Either format_ip4_address_and_length or format_ip6_address_and_length.
Definition: lookup.h:155
ip
vl_api_address_t ip
Definition: l2.api:558
ip_interface_address_find
u32 ip_interface_address_find(ip_lookup_main_t *lm, void *addr_fib, u32 address_length)
Definition: ip_interface.c:24
vnet_sw_interface_walk
void vnet_sw_interface_walk(vnet_main_t *vnm, vnet_sw_interface_walk_t fn, void *ctx)
Walk all the SW interfaces in the system.
Definition: interface.c:1164
rv
int __clib_unused rv
Definition: application.c:491
ip_interface_address_t
Definition: lookup.h:89
ip_interface_address_t::next_this_sw_interface
u32 next_this_sw_interface
Definition: lookup.h:105
ip4_main_t
IPv4 main type.
Definition: ip4.h:107
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
walk_rc_t
enum walk_rc_t_ walk_rc_t
Walk return code.
mhash_unset
__clib_export uword mhash_unset(mhash_t *h, void *key, uword *old_value)
Definition: mhash.c:346
mhash_set
static uword mhash_set(mhash_t *h, void *key, uword new_value, uword *old_value)
Definition: mhash.h:117