FD.io VPP  v20.01-rc1
Vector Packet Processing
lb.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 #include <lb/lb.h>
17 #include <vnet/plugin/plugin.h>
18 #include <vpp/app/version.h>
19 #include <vnet/api_errno.h>
20 #include <vnet/udp/udp.h>
21 #include <vppinfra/lock.h>
22 
23 //GC runs at most once every so many seconds
24 #define LB_GARBAGE_RUN 60
25 
26 //After so many seconds. It is assumed that inter-core race condition will not occur.
27 #define LB_CONCURRENCY_TIMEOUT 10
28 
29 // FIB source for adding routes
31 
33 
34 #define lb_get_writer_lock() clib_spinlock_lock (&lb_main.writer_lock)
35 #define lb_put_writer_lock() clib_spinlock_unlock (&lb_main.writer_lock)
36 
37 static void lb_as_stack (lb_as_t *as);
38 
39 
40 const static char * const lb_dpo_gre4_ip4[] = { "lb4-gre4" , NULL };
41 const static char * const lb_dpo_gre4_ip6[] = { "lb6-gre4" , NULL };
42 const static char* const * const lb_dpo_gre4_nodes[DPO_PROTO_NUM] =
43  {
46  };
47 
48 const static char * const lb_dpo_gre6_ip4[] = { "lb4-gre6" , NULL };
49 const static char * const lb_dpo_gre6_ip6[] = { "lb6-gre6" , NULL };
50 const static char* const * const lb_dpo_gre6_nodes[DPO_PROTO_NUM] =
51  {
54  };
55 
56 const static char * const lb_dpo_gre4_ip4_port[] = { "lb4-gre4-port" , NULL };
57 const static char * const lb_dpo_gre4_ip6_port[] = { "lb6-gre4-port" , NULL };
58 const static char* const * const lb_dpo_gre4_port_nodes[DPO_PROTO_NUM] =
59  {
62  };
63 
64 const static char * const lb_dpo_gre6_ip4_port[] = { "lb4-gre6-port" , NULL };
65 const static char * const lb_dpo_gre6_ip6_port[] = { "lb6-gre6-port" , NULL };
66 const static char* const * const lb_dpo_gre6_port_nodes[DPO_PROTO_NUM] =
67  {
70  };
71 
72 const static char * const lb_dpo_l3dsr_ip4[] = {"lb4-l3dsr" , NULL};
73 const static char* const * const lb_dpo_l3dsr_nodes[DPO_PROTO_NUM] =
74  {
76  };
77 
78 const static char * const lb_dpo_l3dsr_ip4_port[] = {"lb4-l3dsr-port" , NULL};
79 const static char* const * const lb_dpo_l3dsr_port_nodes[DPO_PROTO_NUM] =
80  {
82  };
83 
84 const static char * const lb_dpo_nat4_ip4_port[] = { "lb4-nat4-port" , NULL };
85 const static char* const * const lb_dpo_nat4_port_nodes[DPO_PROTO_NUM] =
86  {
88  };
89 
90 const static char * const lb_dpo_nat6_ip6_port[] = { "lb6-nat6-port" , NULL };
91 const static char* const * const lb_dpo_nat6_port_nodes[DPO_PROTO_NUM] =
92  {
94  };
95 
97 {
98  return (u32) (vlib_time_now(vm) + 10000);
99 }
100 
101 u8 *format_lb_main (u8 * s, va_list * args)
102 {
104  lb_main_t *lbm = &lb_main;
105  s = format(s, "lb_main");
106  s = format(s, " ip4-src-address: %U \n", format_ip4_address, &lbm->ip4_src_address);
107  s = format(s, " ip6-src-address: %U \n", format_ip6_address, &lbm->ip6_src_address);
108  s = format(s, " #vips: %u\n", pool_elts(lbm->vips));
109  s = format(s, " #ass: %u\n", pool_elts(lbm->ass) - 1);
110 
111  u32 thread_index;
112  for(thread_index = 0; thread_index < tm->n_vlib_mains; thread_index++ ) {
113  lb_hash_t *h = lbm->per_cpu[thread_index].sticky_ht;
114  if (h) {
115  s = format(s, "core %d\n", thread_index);
116  s = format(s, " timeout: %ds\n", h->timeout);
117  s = format(s, " usage: %d / %d\n", lb_hash_elts(h, lb_hash_time_now(vlib_get_main())), lb_hash_size(h));
118  }
119  }
120 
121  return s;
122 }
123 
124 static char *lb_vip_type_strings[] = {
125  [LB_VIP_TYPE_IP6_GRE6] = "ip6-gre6",
126  [LB_VIP_TYPE_IP6_GRE4] = "ip6-gre4",
127  [LB_VIP_TYPE_IP4_GRE6] = "ip4-gre6",
128  [LB_VIP_TYPE_IP4_GRE4] = "ip4-gre4",
129  [LB_VIP_TYPE_IP4_L3DSR] = "ip4-l3dsr",
130  [LB_VIP_TYPE_IP4_NAT4] = "ip4-nat4",
131  [LB_VIP_TYPE_IP6_NAT6] = "ip6-nat6",
132 };
133 
134 u8 *format_lb_vip_type (u8 * s, va_list * args)
135 {
136  lb_vip_type_t vipt = va_arg (*args, lb_vip_type_t);
137  u32 i;
138  for (i=0; i<LB_VIP_N_TYPES; i++)
139  if (vipt == i)
140  return format(s, lb_vip_type_strings[i]);
141  return format(s, "_WRONG_TYPE_");
142 }
143 
144 uword unformat_lb_vip_type (unformat_input_t * input, va_list * args)
145 {
146  lb_vip_type_t *vipt = va_arg (*args, lb_vip_type_t *);
147  u32 i;
148  for (i=0; i<LB_VIP_N_TYPES; i++)
149  if (unformat(input, lb_vip_type_strings[i])) {
150  *vipt = i;
151  return 1;
152  }
153  return 0;
154 }
155 
156 u8 *format_lb_vip (u8 * s, va_list * args)
157 {
158  lb_vip_t *vip = va_arg (*args, lb_vip_t *);
159  s = format(s, "%U %U new_size:%u #as:%u%s",
160  format_lb_vip_type, vip->type,
162  vip->new_flow_table_mask + 1,
163  pool_elts(vip->as_indexes),
164  (vip->flags & LB_VIP_FLAGS_USED)?"":" removed");
165 
166  if (vip->port != 0)
167  {
168  s = format(s, " protocol:%u port:%u ", vip->protocol, vip->port);
169  }
170 
171  if (vip->type == LB_VIP_TYPE_IP4_L3DSR)
172  {
173  s = format(s, " dscp:%u", vip->encap_args.dscp);
174  }
175  else if ((vip->type == LB_VIP_TYPE_IP4_NAT4)
176  || (vip->type == LB_VIP_TYPE_IP6_NAT6))
177  {
178  s = format (s, " type:%s port:%u target_port:%u",
179  (vip->encap_args.srv_type == LB_SRV_TYPE_CLUSTERIP)?"clusterip":
180  "nodeport",
181  ntohs(vip->port), ntohs(vip->encap_args.target_port));
182  }
183 
184  return s;
185 }
186 
187 u8 *format_lb_as (u8 * s, va_list * args)
188 {
189  lb_as_t *as = va_arg (*args, lb_as_t *);
190  return format(s, "%U %s", format_ip46_address,
191  &as->address, IP46_TYPE_ANY,
192  (as->flags & LB_AS_FLAGS_USED)?"used":"removed");
193 }
194 
195 u8 *format_lb_vip_detailed (u8 * s, va_list * args)
196 {
197  lb_main_t *lbm = &lb_main;
198  lb_vip_t *vip = va_arg (*args, lb_vip_t *);
199  u32 indent = format_get_indent (s);
200 
201  s = format(s, "%U %U [%lu] %U%s\n"
202  "%U new_size:%u\n",
203  format_white_space, indent,
204  format_lb_vip_type, vip->type,
205  vip - lbm->vips,
207  (vip->flags & LB_VIP_FLAGS_USED)?"":" removed",
208  format_white_space, indent,
209  vip->new_flow_table_mask + 1);
210 
211  if (vip->port != 0)
212  {
213  s = format(s, "%U protocol:%u port:%u\n",
214  format_white_space, indent,
215  vip->protocol, vip->port);
216  }
217 
218  if (vip->type == LB_VIP_TYPE_IP4_L3DSR)
219  {
220  s = format(s, "%U dscp:%u\n",
221  format_white_space, indent,
222  vip->encap_args.dscp);
223  }
224  else if ((vip->type == LB_VIP_TYPE_IP4_NAT4)
225  || (vip->type == LB_VIP_TYPE_IP6_NAT6))
226  {
227  s = format (s, "%U type:%s port:%u target_port:%u",
228  format_white_space, indent,
229  (vip->encap_args.srv_type == LB_SRV_TYPE_CLUSTERIP)?"clusterip":
230  "nodeport",
231  ntohs(vip->port), ntohs(vip->encap_args.target_port));
232  }
233 
234  //Print counters
235  s = format(s, "%U counters:\n",
236  format_white_space, indent);
237  u32 i;
238  for (i=0; i<LB_N_VIP_COUNTERS; i++)
239  s = format(s, "%U %s: %Lu\n",
240  format_white_space, indent,
241  lbm->vip_counters[i].name,
242  vlib_get_simple_counter(&lbm->vip_counters[i], vip - lbm->vips));
243 
244 
245  s = format(s, "%U #as:%u\n",
246  format_white_space, indent,
247  pool_elts(vip->as_indexes));
248 
249  //Let's count the buckets for each AS
250  u32 *count = 0;
251  vec_validate(count, pool_len(lbm->ass)); //Possibly big alloc for not much...
252  lb_new_flow_entry_t *nfe;
253  vec_foreach(nfe, vip->new_flow_table)
254  count[nfe->as_index]++;
255 
256  lb_as_t *as;
257  u32 *as_index;
258  pool_foreach(as_index, vip->as_indexes, {
259  as = &lbm->ass[*as_index];
260  s = format(s, "%U %U %u buckets %Lu flows dpo:%u %s\n",
261  format_white_space, indent,
262  format_ip46_address, &as->address, IP46_TYPE_ANY,
263  count[as - lbm->ass],
264  vlib_refcount_get(&lbm->as_refcount, as - lbm->ass),
265  as->dpo.dpoi_index,
266  (as->flags & LB_AS_FLAGS_USED)?"used":" removed");
267  });
268 
269  vec_free(count);
270  return s;
271 }
272 
273 typedef struct {
278 
279 static int lb_pseudorand_compare(void *a, void *b)
280 {
281  lb_as_t *asa, *asb;
282  lb_main_t *lbm = &lb_main;
283  asa = &lbm->ass[((lb_pseudorand_t *)a)->as_index];
284  asb = &lbm->ass[((lb_pseudorand_t *)b)->as_index];
285  return memcmp(&asa->address, &asb->address, sizeof(asb->address));
286 }
287 
289 {
290  lb_main_t *lbm = &lb_main;
291  lb_snat4_key_t m_key4;
292  clib_bihash_kv_8_8_t kv4, value4;
293  lb_snat6_key_t m_key6;
294  clib_bihash_kv_24_8_t kv6, value6;
295  lb_snat_mapping_t *m = 0;
297 
298  u32 now = (u32) vlib_time_now(vlib_get_main());
300  return;
301 
302  vip->last_garbage_collection = now;
303  lb_as_t *as;
304  u32 *as_index;
305  pool_foreach(as_index, vip->as_indexes, {
306  as = &lbm->ass[*as_index];
307  if (!(as->flags & LB_AS_FLAGS_USED) && //Not used
308  clib_u32_loop_gt(now, as->last_used + LB_CONCURRENCY_TIMEOUT) &&
309  (vlib_refcount_get(&lbm->as_refcount, as - lbm->ass) == 0))
310  { //Not referenced
311 
312  if (lb_vip_is_nat4_port(vip)) {
313  m_key4.addr = as->address.ip4;
314  m_key4.port = vip->encap_args.target_port;
315  m_key4.protocol = 0;
316  m_key4.fib_index = 0;
317 
318  kv4.key = m_key4.as_u64;
319  if(!clib_bihash_search_8_8(&lbm->mapping_by_as4, &kv4, &value4))
320  m = pool_elt_at_index (lbm->snat_mappings, value4.value);
321  ASSERT (m);
322 
323  kv4.value = m - lbm->snat_mappings;
324  clib_bihash_add_del_8_8(&lbm->mapping_by_as4, &kv4, 0);
325  pool_put (lbm->snat_mappings, m);
326  } else if (lb_vip_is_nat6_port(vip)) {
327  m_key6.addr.as_u64[0] = as->address.ip6.as_u64[0];
328  m_key6.addr.as_u64[1] = as->address.ip6.as_u64[1];
329  m_key6.port = vip->encap_args.target_port;
330  m_key6.protocol = 0;
331  m_key6.fib_index = 0;
332 
333  kv6.key[0] = m_key6.as_u64[0];
334  kv6.key[1] = m_key6.as_u64[1];
335  kv6.key[2] = m_key6.as_u64[2];
336 
337  if (!clib_bihash_search_24_8 (&lbm->mapping_by_as6, &kv6, &value6))
338  m = pool_elt_at_index (lbm->snat_mappings, value6.value);
339  ASSERT (m);
340 
341  kv6.value = m - lbm->snat_mappings;
342  clib_bihash_add_del_24_8(&lbm->mapping_by_as6, &kv6, 0);
343  pool_put (lbm->snat_mappings, m);
344  }
345  fib_entry_child_remove(as->next_hop_fib_entry_index,
346  as->next_hop_child_index);
347  fib_table_entry_delete_index(as->next_hop_fib_entry_index,
348  FIB_SOURCE_RR);
349  as->next_hop_fib_entry_index = FIB_NODE_INDEX_INVALID;
350 
351  pool_put(vip->as_indexes, as_index);
352  pool_put(lbm->ass, as);
353  }
354  });
355 }
356 
358 {
359  lb_main_t *lbm = &lb_main;
361  lb_vip_t *vip;
362  u32 *to_be_removed_vips = 0, *i;
363  pool_foreach(vip, lbm->vips, {
364  lb_vip_garbage_collection(vip);
365 
366  if (!(vip->flags & LB_VIP_FLAGS_USED) &&
367  (pool_elts(vip->as_indexes) == 0)) {
368  vec_add1(to_be_removed_vips, vip - lbm->vips);
369  }
370  });
371 
372  vec_foreach(i, to_be_removed_vips) {
373  vip = &lbm->vips[*i];
374  pool_put(lbm->vips, vip);
375  pool_free(vip->as_indexes);
376  }
377 
378  vec_free(to_be_removed_vips);
380 }
381 
383 {
384  lb_main_t *lbm = &lb_main;
385  lb_new_flow_entry_t *old_table;
386  u32 i, *as_index;
387  lb_new_flow_entry_t *new_flow_table = 0;
388  lb_as_t *as;
389  lb_pseudorand_t *pr, *sort_arr = 0;
390 
391  CLIB_SPINLOCK_ASSERT_LOCKED (&lbm->writer_lock); // We must have the lock
392 
393  //Check if some AS is configured or not
394  i = 0;
395  pool_foreach(as_index, vip->as_indexes, {
396  as = &lbm->ass[*as_index];
397  if (as->flags & LB_AS_FLAGS_USED) { //Not used anymore
398  i = 1;
399  goto out; //Not sure 'break' works in this macro-loop
400  }
401  });
402 
403 out:
404  if (i == 0) {
405  //Only the default. i.e. no AS
406  vec_validate(new_flow_table, vip->new_flow_table_mask);
407  for (i=0; i<vec_len(new_flow_table); i++)
408  new_flow_table[i].as_index = 0;
409 
410  goto finished;
411  }
412 
413  //First, let's sort the ASs
414  vec_alloc(sort_arr, pool_elts(vip->as_indexes));
415 
416  i = 0;
417  pool_foreach(as_index, vip->as_indexes, {
418  as = &lbm->ass[*as_index];
419  if (!(as->flags & LB_AS_FLAGS_USED)) //Not used anymore
420  continue;
421 
422  sort_arr[i].as_index = as - lbm->ass;
423  i++;
424  });
425  _vec_len(sort_arr) = i;
426 
428 
429  //Now let's pseudo-randomly generate permutations
430  vec_foreach(pr, sort_arr) {
431  lb_as_t *as = &lbm->ass[pr->as_index];
432 
433  u64 seed = clib_xxhash(as->address.as_u64[0] ^
434  as->address.as_u64[1]);
435  /* We have 2^n buckets.
436  * skip must be prime with 2^n.
437  * So skip must be odd.
438  * MagLev actually state that M should be prime,
439  * but this has a big computation cost (% operation).
440  * Using 2^n is more better (& operation).
441  */
442  pr->skip = ((seed & 0xffffffff) | 1) & vip->new_flow_table_mask;
443  pr->last = (seed >> 32) & vip->new_flow_table_mask;
444  }
445 
446  //Let's create a new flow table
447  vec_validate(new_flow_table, vip->new_flow_table_mask);
448  for (i=0; i<vec_len(new_flow_table); i++)
449  new_flow_table[i].as_index = 0;
450 
451  u32 done = 0;
452  while (1) {
453  vec_foreach(pr, sort_arr) {
454  while (1) {
455  u32 last = pr->last;
456  pr->last = (pr->last + pr->skip) & vip->new_flow_table_mask;
457  if (new_flow_table[last].as_index == 0) {
458  new_flow_table[last].as_index = pr->as_index;
459  break;
460  }
461  }
462  done++;
463  if (done == vec_len(new_flow_table))
464  goto finished;
465  }
466  }
467 
468 finished:
469  vec_free(sort_arr);
470 
471  old_table = vip->new_flow_table;
472  vip->new_flow_table = new_flow_table;
473  vec_free(old_table);
474 }
475 
477  u32 per_cpu_sticky_buckets, u32 flow_timeout)
478 {
479  lb_main_t *lbm = &lb_main;
480 
481  if (!is_pow2(per_cpu_sticky_buckets))
482  return VNET_API_ERROR_INVALID_MEMORY_SIZE;
483 
484  lb_get_writer_lock(); //Not exactly necessary but just a reminder that it exists for my future self
487  lbm->per_cpu_sticky_buckets = per_cpu_sticky_buckets;
488  lbm->flow_timeout = flow_timeout;
490  return 0;
491 }
492 
493 
494 
495 static
496 int lb_vip_port_find_index(ip46_address_t *prefix, u8 plen,
497  u8 protocol, u16 port,
498  lb_lkp_type_t lkp_type,
499  u32 *vip_index)
500 {
501  lb_main_t *lbm = &lb_main;
502  lb_vip_t *vip;
503  /* This must be called with the lock owned */
505  ip46_prefix_normalize(prefix, plen);
506  pool_foreach(vip, lbm->vips, {
507  if ((vip->flags & LB_AS_FLAGS_USED) &&
508  vip->plen == plen &&
509  vip->prefix.as_u64[0] == prefix->as_u64[0] &&
510  vip->prefix.as_u64[1] == prefix->as_u64[1])
511  {
512  if((lkp_type == LB_LKP_SAME_IP_PORT &&
513  vip->protocol == protocol &&
514  vip->port == port) ||
515  (lkp_type == LB_LKP_ALL_PORT_IP &&
516  vip->port == 0) ||
517  (lkp_type == LB_LKP_DIFF_IP_PORT &&
518  (vip->protocol != protocol ||
519  vip->port != port) ) )
520  {
521  *vip_index = vip - lbm->vips;
522  return 0;
523  }
524  }
525  });
526  return VNET_API_ERROR_NO_SUCH_ENTRY;
527 }
528 
529 static
530 int lb_vip_port_find_index_with_lock(ip46_address_t *prefix, u8 plen,
531  u8 protocol, u16 port, u32 *vip_index)
532 {
533  return lb_vip_port_find_index(prefix, plen, protocol, port,
534  LB_LKP_SAME_IP_PORT, vip_index);
535 }
536 
537 static
538 int lb_vip_port_find_all_port_vip(ip46_address_t *prefix, u8 plen,
539  u32 *vip_index)
540 {
541  return lb_vip_port_find_index(prefix, plen, ~0, 0,
542  LB_LKP_ALL_PORT_IP, vip_index);
543 }
544 
545 /* Find out per-port-vip entry with different protocol and port */
546 static
547 int lb_vip_port_find_diff_port(ip46_address_t *prefix, u8 plen,
548  u8 protocol, u16 port, u32 *vip_index)
549 {
550  return lb_vip_port_find_index(prefix, plen, protocol, port,
551  LB_LKP_DIFF_IP_PORT, vip_index);
552 }
553 
554 int lb_vip_find_index(ip46_address_t *prefix, u8 plen, u8 protocol,
555  u16 port, u32 *vip_index)
556 {
557  int ret;
559  ret = lb_vip_port_find_index_with_lock(prefix, plen,
560  protocol, port, vip_index);
562  return ret;
563 }
564 
565 static int lb_as_find_index_vip(lb_vip_t *vip, ip46_address_t *address, u32 *as_index)
566 {
567  lb_main_t *lbm = &lb_main;
568  /* This must be called with the lock owned */
570  lb_as_t *as;
571  u32 *asi;
572  pool_foreach(asi, vip->as_indexes, {
573  as = &lbm->ass[*asi];
574  if (as->vip_index == (vip - lbm->vips) &&
575  as->address.as_u64[0] == address->as_u64[0] &&
576  as->address.as_u64[1] == address->as_u64[1])
577  {
578  *as_index = as - lbm->ass;
579  return 0;
580  }
581  });
582  return -1;
583 }
584 
585 int lb_vip_add_ass(u32 vip_index, ip46_address_t *addresses, u32 n)
586 {
587  lb_main_t *lbm = &lb_main;
589  lb_vip_t *vip;
590  if (!(vip = lb_vip_get_by_index(vip_index))) {
592  return VNET_API_ERROR_NO_SUCH_ENTRY;
593  }
594 
596  u32 *to_be_added = 0;
597  u32 *to_be_updated = 0;
598  u32 i;
599  u32 *ip;
601 
602  //Sanity check
603  while (n--) {
604 
605  if (!lb_as_find_index_vip(vip, &addresses[n], &i)) {
606  if (lbm->ass[i].flags & LB_AS_FLAGS_USED) {
607  vec_free(to_be_added);
608  vec_free(to_be_updated);
610  return VNET_API_ERROR_VALUE_EXIST;
611  }
612  vec_add1(to_be_updated, i);
613  goto next;
614  }
615 
616  if (ip46_address_type(&addresses[n]) != type) {
617  vec_free(to_be_added);
618  vec_free(to_be_updated);
620  return VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
621  }
622 
623  if (n) {
624  u32 n2 = n;
625  while(n2--) //Check for duplicates
626  if (addresses[n2].as_u64[0] == addresses[n].as_u64[0] &&
627  addresses[n2].as_u64[1] == addresses[n].as_u64[1])
628  goto next;
629  }
630 
631  vec_add1(to_be_added, n);
632 
633 next:
634  continue;
635  }
636 
637  //Update reused ASs
638  vec_foreach(ip, to_be_updated) {
639  lbm->ass[*ip].flags = LB_AS_FLAGS_USED;
640  }
641  vec_free(to_be_updated);
642 
643  //Create those who have to be created
644  vec_foreach(ip, to_be_added) {
645  lb_as_t *as;
646  u32 *as_index;
647  pool_get(lbm->ass, as);
648  as->address = addresses[*ip];
649  as->flags = LB_AS_FLAGS_USED;
650  as->vip_index = vip_index;
651  pool_get(vip->as_indexes, as_index);
652  *as_index = as - lbm->ass;
653 
654  /*
655  * become a child of the FIB entry
656  * so we are informed when its forwarding changes
657  */
658  fib_prefix_t nh = {};
659  if (lb_encap_is_ip4(vip)) {
660  nh.fp_addr.ip4 = as->address.ip4;
661  nh.fp_len = 32;
663  } else {
664  nh.fp_addr.ip6 = as->address.ip6;
665  nh.fp_len = 128;
667  }
668 
671  &nh,
676  lbm->fib_node_type,
677  as - lbm->ass);
678 
679  lb_as_stack(as);
680 
681  if ( lb_vip_is_nat4_port(vip) || lb_vip_is_nat6_port(vip) )
682  {
683  /* Add SNAT static mapping */
684  pool_get (lbm->snat_mappings, m);
685  clib_memset (m, 0, sizeof (*m));
686  if (lb_vip_is_nat4_port(vip)) {
687  lb_snat4_key_t m_key4;
689  m_key4.addr = as->address.ip4;
690  m_key4.port = vip->encap_args.target_port;
691  m_key4.protocol = 0;
692  m_key4.fib_index = 0;
693 
695  {
696  m->src_ip.ip4 = vip->prefix.ip4;
697  }
698  else if (vip->encap_args.srv_type == LB_SRV_TYPE_NODEPORT)
699  {
700  m->src_ip.ip4 = lbm->ip4_src_address;
701  }
702  m->src_ip_is_ipv6 = 0;
703  m->as_ip.ip4 = as->address.ip4;
704  m->as_ip_is_ipv6 = 0;
705  m->src_port = vip->port;
707  m->vrf_id = 0;
708  m->fib_index = 0;
709 
710  kv4.key = m_key4.as_u64;
711  kv4.value = m - lbm->snat_mappings;
712  clib_bihash_add_del_8_8(&lbm->mapping_by_as4, &kv4, 1);
713  } else {
714  lb_snat6_key_t m_key6;
716  m_key6.addr.as_u64[0] = as->address.ip6.as_u64[0];
717  m_key6.addr.as_u64[1] = as->address.ip6.as_u64[1];
718  m_key6.port = vip->encap_args.target_port;
719  m_key6.protocol = 0;
720  m_key6.fib_index = 0;
721 
723  {
724  m->src_ip.ip6.as_u64[0] = vip->prefix.ip6.as_u64[0];
725  m->src_ip.ip6.as_u64[1] = vip->prefix.ip6.as_u64[1];
726  }
727  else if (vip->encap_args.srv_type == LB_SRV_TYPE_NODEPORT)
728  {
729  m->src_ip.ip6.as_u64[0] = lbm->ip6_src_address.as_u64[0];
730  m->src_ip.ip6.as_u64[1] = lbm->ip6_src_address.as_u64[1];
731  }
732  m->src_ip_is_ipv6 = 1;
733  m->as_ip.ip6.as_u64[0] = as->address.ip6.as_u64[0];
734  m->as_ip.ip6.as_u64[1] = as->address.ip6.as_u64[1];
735  m->as_ip_is_ipv6 = 1;
736  m->src_port = vip->port;
738  m->vrf_id = 0;
739  m->fib_index = 0;
740 
741  kv6.key[0] = m_key6.as_u64[0];
742  kv6.key[1] = m_key6.as_u64[1];
743  kv6.key[2] = m_key6.as_u64[2];
744  kv6.value = m - lbm->snat_mappings;
745  clib_bihash_add_del_24_8(&lbm->mapping_by_as6, &kv6, 1);
746  }
747  }
748  }
749  vec_free(to_be_added);
750 
751  //Recompute flows
753 
754  //Garbage collection maybe
756 
758  return 0;
759 }
760 
761 int
762 lb_flush_vip_as (u32 vip_index, u32 as_index)
763 {
764  u32 thread_index;
766  lb_main_t *lbm = &lb_main;
767 
768  for(thread_index = 0; thread_index < tm->n_vlib_mains; thread_index++ ) {
769  lb_hash_t *h = lbm->per_cpu[thread_index].sticky_ht;
770  if (h != NULL) {
771  u32 i;
772  lb_hash_bucket_t *b;
773 
774  lb_hash_foreach_entry(h, b, i) {
775  if ((vip_index == ~0)
776  || ((b->vip[i] == vip_index) && (as_index == ~0))
777  || ((b->vip[i] == vip_index) && (b->value[i] == as_index)))
778  {
779  vlib_refcount_add(&lbm->as_refcount, thread_index, b->value[i], -1);
780  vlib_refcount_add(&lbm->as_refcount, thread_index, 0, 1);
781  b->vip[i] = ~0;
782  b->value[i] = 0;
783  }
784  }
785  if (vip_index == ~0)
786  {
787  lb_hash_free(h);
788  lbm->per_cpu[thread_index].sticky_ht = 0;
789  }
790  }
791  }
792 
793  return 0;
794 }
795 
796 int lb_vip_del_ass_withlock(u32 vip_index, ip46_address_t *addresses, u32 n,
797  u8 flush)
798 {
799  lb_main_t *lbm = &lb_main;
800  u32 now = (u32) vlib_time_now(vlib_get_main());
801  u32 *ip = 0;
802  u32 as_index = 0;
803 
804  lb_vip_t *vip;
805  if (!(vip = lb_vip_get_by_index(vip_index))) {
806  return VNET_API_ERROR_NO_SUCH_ENTRY;
807  }
808 
809  u32 *indexes = NULL;
810  while (n--) {
811  if (lb_as_find_index_vip(vip, &addresses[n], &as_index)) {
812  vec_free(indexes);
813  return VNET_API_ERROR_NO_SUCH_ENTRY;
814  }
815 
816  if (n) { //Check for duplicates
817  u32 n2 = n - 1;
818  while(n2--) {
819  if (addresses[n2].as_u64[0] == addresses[n].as_u64[0] &&
820  addresses[n2].as_u64[1] == addresses[n].as_u64[1])
821  goto next;
822  }
823  }
824 
825  vec_add1(indexes, as_index);
826 next:
827  continue;
828  }
829 
830  //Garbage collection maybe
832 
833  if (indexes != NULL) {
834  vec_foreach(ip, indexes) {
835  lbm->ass[*ip].flags &= ~LB_AS_FLAGS_USED;
836  lbm->ass[*ip].last_used = now;
837 
838  if(flush)
839  {
840  /* flush flow table for deleted ASs*/
841  lb_flush_vip_as(vip_index, *ip);
842  }
843  }
844 
845  //Recompute flows
847  }
848 
849  vec_free(indexes);
850  return 0;
851 }
852 
853 int lb_vip_del_ass(u32 vip_index, ip46_address_t *addresses, u32 n, u8 flush)
854 {
856  int ret = lb_vip_del_ass_withlock(vip_index, addresses, n, flush);
858 
859  return ret;
860 }
861 
862 static int
864 {
865  /*
866  * Check for dynamically allocated instance number.
867  */
868  u32 bit;
869 
871 
873 
874  return bit;
875 }
876 
877 static int
879 {
880 
881  if (clib_bitmap_get (lbm->vip_prefix_indexes, instance) == 0)
882  {
883  return -1;
884  }
885 
887  instance, 0);
888 
889  return 0;
890 }
891 
892 /**
893  * Add the VIP adjacency to the ip4 or ip6 fib
894  */
895 static void lb_vip_add_adjacency(lb_main_t *lbm, lb_vip_t *vip,
896  u32 *vip_prefix_index)
897 {
898  dpo_proto_t proto = 0;
899  dpo_type_t dpo_type = 0;
900  u32 vip_idx = 0;
901 
902  if (vip->port != 0)
903  {
904  /* for per-port vip, if VIP adjacency has been added,
905  * no need to add adjacency. */
906  if (!lb_vip_port_find_diff_port(&(vip->prefix), vip->plen,
907  vip->protocol, vip->port, &vip_idx))
908  {
909  return;
910  }
911 
912  /* Allocate an index for per-port vip */
913  *vip_prefix_index = lb_vip_prefix_index_alloc(lbm);
914  }
915  else
916  {
917  *vip_prefix_index = vip - lbm->vips;
918  }
919 
920  dpo_id_t dpo = DPO_INVALID;
921  fib_prefix_t pfx = {};
922  if (lb_vip_is_ip4(vip->type)) {
923  pfx.fp_addr.ip4 = vip->prefix.ip4;
924  pfx.fp_len = vip->plen - 96;
926  proto = DPO_PROTO_IP4;
927  } else {
928  pfx.fp_addr.ip6 = vip->prefix.ip6;
929  pfx.fp_len = vip->plen;
931  proto = DPO_PROTO_IP6;
932  }
933 
934  if (lb_vip_is_gre4(vip))
935  dpo_type = lbm->dpo_gre4_type;
936  else if (lb_vip_is_gre6(vip))
937  dpo_type = lbm->dpo_gre6_type;
938  else if (lb_vip_is_gre4_port(vip))
939  dpo_type = lbm->dpo_gre4_port_type;
940  else if (lb_vip_is_gre6_port(vip))
941  dpo_type = lbm->dpo_gre6_port_type;
942  else if (lb_vip_is_l3dsr(vip))
943  dpo_type = lbm->dpo_l3dsr_type;
944  else if (lb_vip_is_l3dsr_port(vip))
945  dpo_type = lbm->dpo_l3dsr_port_type;
946  else if(lb_vip_is_nat4_port(vip))
947  dpo_type = lbm->dpo_nat4_port_type;
948  else if (lb_vip_is_nat6_port(vip))
949  dpo_type = lbm->dpo_nat6_port_type;
950 
951  dpo_set(&dpo, dpo_type, proto, *vip_prefix_index);
953  &pfx,
954  lb_fib_src,
956  &dpo);
957  dpo_reset(&dpo);
958 }
959 
960 /**
961  * Add the VIP filter entry
962  */
964  u32 vip_prefix_index, u32 vip_idx)
965 {
968 
969  key.vip_prefix_index = vip_prefix_index;
970  key.protocol = vip->protocol;
971  key.port = clib_host_to_net_u16(vip->port);
972  key.rsv = 0;
973 
974  kv.key = key.as_u64;
975  kv.value = vip_idx;
976  clib_bihash_add_del_8_8(&lbm->vip_index_per_port, &kv, 1);
977 
978  return 0;
979 }
980 
981 /**
982  * Del the VIP filter entry
983  */
985 {
988  lb_vip_t *m = 0;
989 
991  key.protocol = vip->protocol;
992  key.port = clib_host_to_net_u16(vip->port);
993  key.rsv = 0;
994 
995  kv.key = key.as_u64;
996  if(clib_bihash_search_8_8(&lbm->vip_index_per_port, &kv, &value) != 0)
997  {
998  clib_warning("looking up vip_index_per_port failed.");
999  return VNET_API_ERROR_NO_SUCH_ENTRY;
1000  }
1001  m = pool_elt_at_index (lbm->vips, value.value);
1002  ASSERT (m);
1003 
1004  kv.value = m - lbm->vips;
1005  clib_bihash_add_del_8_8(&lbm->vip_index_per_port, &kv, 0);
1006 
1007  return 0;
1008 }
1009 
1010 /**
1011  * Deletes the adjacency associated with the VIP
1012  */
1013 static void lb_vip_del_adjacency(lb_main_t *lbm, lb_vip_t *vip)
1014 {
1015  fib_prefix_t pfx = {};
1016  u32 vip_idx = 0;
1017 
1018  if (vip->port != 0)
1019  {
1020  /* If this vip adjacency is used by other per-port vip,
1021  * no need to del this adjacency. */
1022  if (!lb_vip_port_find_diff_port(&(vip->prefix), vip->plen,
1023  vip->protocol, vip->port, &vip_idx))
1024  {
1026  return;
1027  }
1028 
1029  /* Return vip_prefix_index for per-port vip */
1031 
1032  }
1033 
1034  if (lb_vip_is_ip4(vip->type)) {
1035  pfx.fp_addr.ip4 = vip->prefix.ip4;
1036  pfx.fp_len = vip->plen - 96;
1037  pfx.fp_proto = FIB_PROTOCOL_IP4;
1038  } else {
1039  pfx.fp_addr.ip6 = vip->prefix.ip6;
1040  pfx.fp_len = vip->plen;
1041  pfx.fp_proto = FIB_PROTOCOL_IP6;
1042  }
1044 }
1045 
1046 int lb_vip_add(lb_vip_add_args_t args, u32 *vip_index)
1047 {
1048  lb_main_t *lbm = &lb_main;
1050  lb_vip_t *vip;
1051  lb_vip_type_t type = args.type;
1052  u32 vip_prefix_index = 0;
1053 
1055  ip46_prefix_normalize(&(args.prefix), args.plen);
1056 
1057  if (!lb_vip_port_find_index_with_lock(&(args.prefix), args.plen,
1058  args.protocol, args.port,
1059  vip_index))
1060  {
1062  return VNET_API_ERROR_VALUE_EXIST;
1063  }
1064 
1065  /* Make sure we can't add a per-port VIP entry
1066  * when there already is an all-port VIP for the same prefix. */
1067  if ((args.port != 0) &&
1068  !lb_vip_port_find_all_port_vip(&(args.prefix), args.plen, vip_index))
1069  {
1071  return VNET_API_ERROR_VALUE_EXIST;
1072  }
1073 
1074  /* Make sure we can't add a all-port VIP entry
1075  * when there already is an per-port VIP for the same prefix. */
1076  if ((args.port == 0) &&
1077  !lb_vip_port_find_diff_port(&(args.prefix), args.plen,
1078  args.protocol, args.port, vip_index))
1079  {
1081  return VNET_API_ERROR_VALUE_EXIST;
1082  }
1083 
1084  /* Make sure all VIP for a given prefix (using different ports) have the same type. */
1085  if ((args.port != 0) &&
1086  !lb_vip_port_find_diff_port(&(args.prefix), args.plen,
1087  args.protocol, args.port, vip_index)
1088  && (args.type != lbm->vips[*vip_index].type))
1089  {
1091  return VNET_API_ERROR_INVALID_ARGUMENT;
1092  }
1093 
1094  if (!is_pow2(args.new_length)) {
1096  return VNET_API_ERROR_INVALID_MEMORY_SIZE;
1097  }
1098 
1099  if (ip46_prefix_is_ip4(&(args.prefix), args.plen) &&
1100  !lb_vip_is_ip4(type)) {
1102  return VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
1103  }
1104 
1105  if ((!ip46_prefix_is_ip4(&(args.prefix), args.plen)) &&
1106  !lb_vip_is_ip6(type)) {
1108  return VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
1109  }
1110 
1111  if ((type == LB_VIP_TYPE_IP4_L3DSR) &&
1112  (args.encap_args.dscp >= 64) )
1113  {
1115  return VNET_API_ERROR_VALUE_EXIST;
1116  }
1117 
1118  //Allocate
1119  pool_get(lbm->vips, vip);
1120 
1121  //Init
1122  memcpy (&(vip->prefix), &(args.prefix), sizeof(args.prefix));
1123  vip->plen = args.plen;
1124  if (args.port != 0)
1125  {
1126  vip->protocol = args.protocol;
1127  vip->port = args.port;
1128  }
1129  else
1130  {
1131  vip->protocol = (u8)~0;
1132  vip->port = 0;
1133  }
1135  vip->type = args.type;
1136 
1137  if (args.type == LB_VIP_TYPE_IP4_L3DSR) {
1138  vip->encap_args.dscp = args.encap_args.dscp;
1139  }
1140  else if ((args.type == LB_VIP_TYPE_IP4_NAT4)
1141  ||(args.type == LB_VIP_TYPE_IP6_NAT6)) {
1142  vip->encap_args.srv_type = args.encap_args.srv_type;
1143  vip->encap_args.target_port =
1144  clib_host_to_net_u16(args.encap_args.target_port);
1145  }
1146 
1147  vip->flags = LB_VIP_FLAGS_USED;
1148  vip->as_indexes = 0;
1149 
1150  //Validate counters
1151  u32 i;
1152  for (i = 0; i < LB_N_VIP_COUNTERS; i++) {
1153  vlib_validate_simple_counter(&lbm->vip_counters[i], vip - lbm->vips);
1154  vlib_zero_simple_counter(&lbm->vip_counters[i], vip - lbm->vips);
1155  }
1156 
1157  //Configure new flow table
1158  vip->new_flow_table_mask = args.new_length - 1;
1159  vip->new_flow_table = 0;
1160 
1161  //Update flow hash table
1163 
1164  //Create adjacency to direct traffic
1165  lb_vip_add_adjacency(lbm, vip, &vip_prefix_index);
1166 
1167  if ( (lb_vip_is_nat4_port(vip) || lb_vip_is_nat6_port(vip))
1169  {
1170  u32 key;
1171  uword * entry;
1172 
1173  //Create maping from nodeport to vip_index
1174  key = clib_host_to_net_u16(args.port);
1175  entry = hash_get_mem (lbm->vip_index_by_nodeport, &key);
1176  if (entry) {
1178  return VNET_API_ERROR_VALUE_EXIST;
1179  }
1180 
1181  hash_set_mem (lbm->vip_index_by_nodeport, &key, vip - lbm->vips);
1182 
1183  /* receive packets destined to NodeIP:NodePort */
1184  udp_register_dst_port (vm, args.port, lb4_nodeport_node.index, 1);
1185  udp_register_dst_port (vm, args.port, lb6_nodeport_node.index, 0);
1186  }
1187 
1188  *vip_index = vip - lbm->vips;
1189  //Create per-port vip filtering table
1190  if (args.port != 0)
1191  {
1192  lb_vip_add_port_filter(lbm, vip, vip_prefix_index, *vip_index);
1193  vip->vip_prefix_index = vip_prefix_index;
1194  }
1195 
1197  return 0;
1198 }
1199 
1200 int lb_vip_del(u32 vip_index)
1201 {
1202  lb_main_t *lbm = &lb_main;
1203  lb_vip_t *vip;
1204  int rv = 0;
1205 
1206  /* Does not remove default vip, i.e. vip_index = 0 */
1207  if (vip_index == 0)
1208  return VNET_API_ERROR_INVALID_VALUE;
1209 
1211  if (!(vip = lb_vip_get_by_index(vip_index))) {
1213  return VNET_API_ERROR_NO_SUCH_ENTRY;
1214  }
1215 
1216  //FIXME: This operation is actually not working
1217  //We will need to remove state before performing this.
1218 
1219  {
1220  //Remove all ASs
1221  ip46_address_t *ass = 0;
1222  lb_as_t *as;
1223  u32 *as_index;
1224 
1225  pool_foreach(as_index, vip->as_indexes, {
1226  as = &lbm->ass[*as_index];
1227  vec_add1(ass, as->address);
1228  });
1229  if (vec_len(ass))
1230  lb_vip_del_ass_withlock(vip_index, ass, vec_len(ass), 0);
1231  vec_free(ass);
1232  }
1233 
1234  //Delete adjacency
1235  lb_vip_del_adjacency(lbm, vip);
1236 
1237  //Delete per-port vip filtering entry
1238  if (vip->port != 0)
1239  {
1240  rv = lb_vip_del_port_filter(lbm, vip);
1241  }
1242 
1243  //Set the VIP as unused
1244  vip->flags &= ~LB_VIP_FLAGS_USED;
1245 
1247  return rv;
1248 }
1249 
1250 /* *INDENT-OFF* */
1251 VLIB_PLUGIN_REGISTER () = {
1252  .version = VPP_BUILD_VER,
1253  .description = "Load Balancer (LB)",
1254 };
1255 /* *INDENT-ON* */
1256 
1257 u8 *format_lb_dpo (u8 * s, va_list * va)
1258 {
1259  index_t index = va_arg (*va, index_t);
1260  CLIB_UNUSED(u32 indent) = va_arg (*va, u32);
1261  lb_main_t *lbm = &lb_main;
1262  lb_vip_t *vip = pool_elt_at_index (lbm->vips, index);
1263  return format (s, "%U", format_lb_vip, vip);
1264 }
1265 
1266 static void lb_dpo_lock (dpo_id_t *dpo) {}
1267 static void lb_dpo_unlock (dpo_id_t *dpo) {}
1268 
1269 static fib_node_t *
1271 {
1272  lb_main_t *lbm = &lb_main;
1273  lb_as_t *as = pool_elt_at_index (lbm->ass, index);
1274  return (&as->fib_node);
1275 }
1276 
1277 static void
1279 {
1280 }
1281 
1282 static lb_as_t *
1284 {
1285  return ((lb_as_t*)(((char*)node) -
1286  STRUCT_OFFSET_OF(lb_as_t, fib_node)));
1287 }
1288 
1289 static void
1291 {
1292  lb_main_t *lbm = &lb_main;
1293  lb_vip_t *vip = &lbm->vips[as->vip_index];
1294  dpo_type_t dpo_type = 0;
1295 
1296  if (lb_vip_is_gre4(vip))
1297  dpo_type = lbm->dpo_gre4_type;
1298  else if (lb_vip_is_gre6(vip))
1299  dpo_type = lbm->dpo_gre6_type;
1300  else if (lb_vip_is_gre4_port(vip))
1301  dpo_type = lbm->dpo_gre4_port_type;
1302  else if (lb_vip_is_gre6_port(vip))
1303  dpo_type = lbm->dpo_gre6_port_type;
1304  else if (lb_vip_is_l3dsr(vip))
1305  dpo_type = lbm->dpo_l3dsr_type;
1306  else if (lb_vip_is_l3dsr_port(vip))
1307  dpo_type = lbm->dpo_l3dsr_port_type;
1308  else if(lb_vip_is_nat4_port(vip))
1309  dpo_type = lbm->dpo_nat4_port_type;
1310  else if (lb_vip_is_nat6_port(vip))
1311  dpo_type = lbm->dpo_nat6_port_type;
1312 
1313  dpo_stack(dpo_type,
1315  &as->dpo,
1318 }
1319 
1323 {
1325  return (FIB_NODE_BACK_WALK_CONTINUE);
1326 }
1327 
1329 {
1330  if (is_del)
1331  {
1332  vnet_feature_enable_disable ("ip4-unicast", "lb-nat4-in2out",
1333  sw_if_index, 0, 0, 0);
1334  }
1335  else
1336  {
1337  vnet_feature_enable_disable ("ip4-unicast", "lb-nat4-in2out",
1338  sw_if_index, 1, 0, 0);
1339  }
1340 
1341  return 0;
1342 }
1343 
1345 {
1346  if (is_del)
1347  {
1348  vnet_feature_enable_disable ("ip6-unicast", "lb-nat6-in2out",
1349  sw_if_index, 0, 0, 0);
1350  }
1351  else
1352  {
1353  vnet_feature_enable_disable ("ip6-unicast", "lb-nat6-in2out",
1354  sw_if_index, 1, 0, 0);
1355  }
1356 
1357  return 0;
1358 }
1359 
1360 clib_error_t *
1362 {
1364  lb_main_t *lbm = &lb_main;
1365  lbm->vnet_main = vnet_get_main ();
1366  lbm->vlib_main = vm;
1367 
1368  lb_vip_t *default_vip;
1369  lb_as_t *default_as;
1370  fib_node_vft_t lb_fib_node_vft = {
1372  .fnv_last_lock = lb_fib_node_last_lock_gone,
1373  .fnv_back_walk = lb_fib_node_back_walk_notify,
1374  };
1375  dpo_vft_t lb_vft = {
1376  .dv_lock = lb_dpo_lock,
1377  .dv_unlock = lb_dpo_unlock,
1378  .dv_format = format_lb_dpo,
1379  };
1380 
1381  //Allocate and init default VIP.
1382  lbm->vips = 0;
1383  pool_get(lbm->vips, default_vip);
1384  default_vip->new_flow_table_mask = 0;
1385  default_vip->prefix.ip6.as_u64[0] = 0xffffffffffffffffL;
1386  default_vip->prefix.ip6.as_u64[1] = 0xffffffffffffffffL;
1387  default_vip->protocol = ~0;
1388  default_vip->port = 0;
1389  default_vip->flags = LB_VIP_FLAGS_USED;
1390 
1391  lbm->per_cpu = 0;
1392  vec_validate(lbm->per_cpu, tm->n_vlib_mains - 1);
1396  lbm->ip4_src_address.as_u32 = 0xffffffff;
1397  lbm->ip6_src_address.as_u64[0] = 0xffffffffffffffffL;
1398  lbm->ip6_src_address.as_u64[1] = 0xffffffffffffffffL;
1405  lbm->dpo_l3dsr_type = dpo_register_new_type(&lb_vft,
1413  lbm->fib_node_type = fib_node_register_new_type(&lb_fib_node_vft);
1414 
1415  //Init AS reference counters
1417 
1418  //Allocate and init default AS.
1419  lbm->ass = 0;
1420  pool_get(lbm->ass, default_as);
1421  default_as->flags = 0;
1422  default_as->dpo.dpoi_next_node = LB_NEXT_DROP;
1423  default_as->vip_index = ~0;
1424  default_as->address.ip6.as_u64[0] = 0xffffffffffffffffL;
1425  default_as->address.ip6.as_u64[1] = 0xffffffffffffffffL;
1426 
1427  /* Generate a valid flow table for default VIP */
1428  default_vip->as_indexes = NULL;
1430  lb_vip_update_new_flow_table(default_vip);
1432 
1434  = hash_create_mem (0, sizeof(u16), sizeof (uword));
1435 
1436  clib_bihash_init_8_8 (&lbm->vip_index_per_port,
1437  "vip_index_per_port", LB_VIP_PER_PORT_BUCKETS,
1439 
1440  clib_bihash_init_8_8 (&lbm->mapping_by_as4,
1441  "mapping_by_as4", LB_MAPPING_BUCKETS,
1443 
1444  clib_bihash_init_24_8 (&lbm->mapping_by_as6,
1445  "mapping_by_as6", LB_MAPPING_BUCKETS,
1447 
1448 #define _(a,b,c) lbm->vip_counters[c].name = b;
1450 #undef _
1451 
1455 
1456  return NULL;
1457 }
1458 
u32 skip
Definition: lb.c:276
int lb_vip_del_ass(u32 vip_index, ip46_address_t *addresses, u32 n, u8 flush)
Definition: lb.c:853
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:440
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
u8 count
Definition: dhcp.api:208
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:406
static void lb_vip_add_adjacency(lb_main_t *lbm, lb_vip_t *vip, u32 *vip_prefix_index)
Add the VIP adjacency to the ip4 or ip6 fib.
Definition: lb.c:895
u64 as_u64
Definition: lb.h:423
enum fib_source_t_ fib_source_t
The different sources that can create a route.
u32 lb_hash_time_now(vlib_main_t *vm)
Definition: lb.c:96
static int lb_vip_port_find_all_port_vip(ip46_address_t *prefix, u8 plen, u32 *vip_index)
Definition: lb.c:538
u64 as_u64[3]
Definition: lb.h:438
int lb_nat4_interface_add_del(u32 sw_if_index, int is_del)
Definition: lb.c:1328
static int lb_pseudorand_compare(void *a, void *b)
Definition: lb.c:279
u8 proto
Definition: acl_types.api:47
vnet_main_t * vnet_main
Definition: lb.h:569
Each VIP is configured with a set of application server.
Definition: lb.h:108
#define LB_GARBAGE_RUN
Definition: lb.c:24
#define CLIB_UNUSED(x)
Definition: clib.h:82
A virtual function table regisitered for a DPO type.
Definition: dpo.h:401
#define lb_vip_is_gre6(vip)
Definition: lb.h:354
a
Definition: bitmap.h:538
static bool lb_vip_is_l3dsr(const lb_vip_t *vip)
Definition: lb.h:367
#define lb_vip_is_gre6_port(vip)
Definition: lb.h:362
u32 last
Definition: lb.c:275
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
u32 fib_index
Definition: lb.h:436
u32 per_cpu_sticky_buckets
Number of buckets in the per-cpu sticky hash table.
Definition: lb.h:522
vl_api_fib_path_nh_t nh
Definition: fib_types.api:126
clib_error_t * lb_init(vlib_main_t *vm)
Definition: lb.c:1361
u64 as_u64
Definition: bihash_doc.h:63
u32 fib_entry_child_add(fib_node_index_t fib_entry_index, fib_node_type_t child_type, fib_node_index_t child_index)
Definition: fib_entry.c:555
static void lb_fib_node_last_lock_gone(fib_node_t *node)
Definition: lb.c:1278
u64 as_u64[2]
Definition: ip6_packet.h:51
static void lb_vip_update_new_flow_table(lb_vip_t *vip)
Definition: lb.c:382
unsigned long u64
Definition: types.h:89
static int lb_as_find_index_vip(lb_vip_t *vip, ip46_address_t *address, u32 *as_index)
Definition: lb.c:565
#define LB_VIP_PER_PORT_MEMORY_SIZE
Definition: lb.h:52
static const char *const lb_dpo_gre4_ip6_port[]
Definition: lb.c:57
manual_print typedef u8 ip4_address[4]
Definition: ip_types.api:18
#define NULL
Definition: clib.h:58
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:279
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
const dpo_id_t * fib_entry_contribute_ip_forwarding(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:506
static int lb_vip_prefix_index_alloc(lb_main_t *lbm)
Definition: lb.c:863
static void lb_vip_del_adjacency(lb_main_t *lbm, lb_vip_t *vip)
Deletes the adjacency associated with the VIP.
Definition: lb.c:1013
int lb_conf(ip4_address_t *ip4_address, ip6_address_t *ip6_address, u32 per_cpu_sticky_buckets, u32 flow_timeout)
Fix global load-balancer parameters.
Definition: lb.c:476
#define lb_get_writer_lock()
Definition: lb.c:34
u8 * format_ip46_prefix(u8 *s, va_list *args)
Definition: util.c:54
int lb_vip_add_ass(u32 vip_index, ip46_address_t *addresses, u32 n)
Definition: lb.c:585
add paths without path extensions
Definition: fib_source.h:205
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:523
ip46_address_t prefix
A Virtual IP represents a given service delivered by a set of application servers.
Definition: lb.h:292
#define clib_u32_loop_gt(a, b)
32 bits integer comparison for running values.
Definition: util.h:38
static u64 clib_xxhash(u64 key)
Definition: xxhash.h:58
static heap_elt_t * last(heap_header_t *h)
Definition: heap.c:53
u16 port
Definition: lb.h:419
static_always_inline void vlib_refcount_init(vlib_refcount_t *r)
Definition: refcount.h:80
int i
static void lb_dpo_lock(dpo_id_t *dpo)
Definition: lb.c:1266
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
u32 vip_prefix_index
Definition: lb.h:245
static u32 format_get_indent(u8 *s)
Definition: format.h:72
#define hash_set_mem(h, key, value)
Definition: hash.h:275
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:65
#define lb_vip_is_ip4(type)
Definition: lb.h:335
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static void lb_as_stack(lb_as_t *as)
Definition: lb.c:1290
vl_api_prefix_t prefix
Definition: ip.api:144
u32 vip[LBHASH_ENTRY_PER_BUCKET]
Definition: lbhash.h:54
#define lb_vip_get_by_index(index)
Definition: lb.h:607
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:237
u32 vip_index
ASs are indexed by address and VIP Index.
Definition: lb.h:127
#define vec_alloc(V, N)
Allocate space for N more elements (no header, unspecified alignment)
Definition: vec.h:281
static const char *const *const lb_dpo_gre6_nodes[DPO_PROTO_NUM]
Definition: lb.c:50
lb_hash_t * sticky_ht
Each CPU has its own sticky flow hash table.
Definition: lb.h:467
unsigned char u8
Definition: types.h:56
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:140
fib_node_type_t fib_node_register_new_type(const fib_node_vft_t *vft)
Create a new FIB node type and Register the function table for it.
Definition: fib_node.c:80
static int lb_vip_del_port_filter(lb_main_t *lbm, lb_vip_t *vip)
Del the VIP filter entry.
Definition: lb.c:984
#define LB_MAPPING_BUCKETS
Definition: lb.h:48
#define LB_VIP_FLAGS_USED
Definition: lb.h:326
#define ip46_address_type(ip46)
Definition: util.h:26
ip46_address_t address
Destination address used to tunnel traffic towards that application server.
Definition: lb.h:120
vl_api_ip_proto_t protocol
Definition: lb_types.api:71
u32 timeout
Definition: lbhash.h:60
static counter_t vlib_get_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Get the value of a simple counter Scrapes the entire set of per-thread counters.
Definition: counter.h:113
format_function_t format_ip4_address
Definition: format.h:73
#define LB_AS_FLAGS_USED
Definition: lb.h:135
enum dpo_type_t_ dpo_type_t
Common types of data-path objects New types can be dynamically added using dpo_register_new_type() ...
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:498
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
u8 as_ip_is_ipv6
Definition: lb.h:450
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
static lb_as_t * lb_as_from_fib_node(fib_node_t *node)
Definition: lb.c:1283
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a &#39;special&#39; entry from the FIB.
Definition: fib_table.c:424
VLIB_PLUGIN_REGISTER()
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
lb_lkp_type_t
Lookup type.
Definition: lb.h:197
#define LB_DEFAULT_PER_CPU_STICKY_BUCKETS
lb-plugin implements a MagLev-like load balancer.
Definition: lb.h:46
#define LB_MAPPING_MEMORY_SIZE
Definition: lb.h:49
lb_main_t lb_main
Definition: lb.c:32
Recursive resolution source.
Definition: fib_source.h:119
static const char *const lb_dpo_gre4_ip4[]
Definition: lb.c:40
u32 flow_timeout
Flow timeout in seconds.
Definition: lb.h:527
u16 port
Definition: lb.h:304
Definition: lb.h:470
fib_node_type_t fib_node_type
Node type for registering to fib changes.
Definition: lb.h:548
dpo_type_t dpo_gre4_type
DPO used to send packet from IP4/6 lookup to LB node.
Definition: lb.h:537
Aggregate type for a prefix.
Definition: fib_types.h:203
u16 protocol
Definition: lb.h:420
static const char *const *const lb_dpo_nat4_port_nodes[DPO_PROTO_NUM]
Definition: lb.c:85
u8 protocol
Definition: lb.h:301
vlib_refcount_t as_refcount
Each AS has an associated reference counter.
Definition: lb.h:494
lb_vip_encap_args_t encap_args
Definition: lb.h:316
static const char *const lb_dpo_gre6_ip4_port[]
Definition: lb.c:64
static void lb_vip_garbage_collection(lb_vip_t *vip)
Definition: lb.c:288
u8 * format_lb_main(u8 *s, va_list *args)
Definition: lb.c:101
uword * vip_prefix_indexes
bitmap for vip prefix to support per-port vip
Definition: lb.h:479
unsigned int u32
Definition: types.h:88
u8 * format_lb_vip(u8 *s, va_list *args)
Definition: lb.c:156
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
u16 fp_len
The mask length.
Definition: fib_types.h:207
vlib_node_registration_t lb6_nodeport_node
(constructor) VLIB_REGISTER_NODE (lb6_nodeport_node)
Definition: node.c:1220
lb_vip_t * vips
Pool of all Virtual IPs.
Definition: lb.h:474
dpo_type_t dpo_register_new_type(const dpo_vft_t *vft, const char *const *const *nodes)
Create and register a new DPO type.
Definition: dpo.c:342
u32 last_used
Rotating timestamp of when LB_AS_FLAGS_USED flag was last set.
Definition: lb.h:146
ip4_address_t ip4_src_address
Source address used for IPv4 encapsulated traffic.
Definition: lb.h:517
static const char *const lb_dpo_l3dsr_ip4_port[]
Definition: lb.c:78
fib_source_t fib_source_allocate(const char *name, fib_source_priority_t prio, fib_source_behaviour_t bh)
Definition: fib_source.c:118
Definition: fib_entry.h:112
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:63
char * name
The counter collection&#39;s name.
Definition: counter.h:64
vl_api_fib_path_type_t type
Definition: fib_types.api:123
u8 plen
The VIP prefix length.
Definition: lb.h:298
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:170
static const char *const lb_dpo_nat6_ip6_port[]
Definition: lb.c:90
static const char *const lb_dpo_nat4_ip4_port[]
Definition: lb.c:84
#define hash_create_mem(elts, key_bytes, value_bytes)
Definition: hash.h:661
Definition: fib_entry.h:116
#define lb_vip_is_gre4(vip)
Definition: lb.h:349
static const char *const lb_dpo_gre6_ip4[]
Definition: lb.c:48
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:519
#define lb_vip_is_gre4_port(vip)
Definition: lb.h:358
static const char *const *const lb_dpo_gre4_port_nodes[DPO_PROTO_NUM]
Definition: lb.c:58
#define lb_encap_is_ip4(vip)
Definition: lb.h:344
u32 value[LBHASH_ENTRY_PER_BUCKET]
Definition: lbhash.h:55
#define FIB_SOURCE_PRIORITY_HI
Some priority values that plugins might use when they are not to concerned where in the list they&#39;ll ...
Definition: fib_source.h:273
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:226
u64 key
the key
Definition: bihash_8_8.h:35
int lb_vip_del(u32 vip_index)
Definition: lb.c:1200
long ctx[MAX_CONNS]
Definition: main.c:144
u8 * format_lb_vip_type(u8 *s, va_list *args)
Definition: lb.c:134
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
u16 src_port
Network byte order for vip + port case, src_port = port; for node ip + node_port, src_port = node_por...
Definition: lb.h:456
static const char *const *const lb_dpo_l3dsr_port_nodes[DPO_PROTO_NUM]
Definition: lb.c:79
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:287
uword unformat_lb_vip_type(unformat_input_t *input, va_list *args)
Definition: lb.c:144
int lb_flush_vip_as(u32 vip_index, u32 as_index)
Definition: lb.c:762
#define LB_DEFAULT_FLOW_TIMEOUT
Definition: lb.h:47
static int lb_vip_port_find_index(ip46_address_t *prefix, u8 plen, u8 protocol, u16 port, lb_lkp_type_t lkp_type, u32 *vip_index)
Definition: lb.c:496
void ip46_prefix_normalize(ip46_address_t *prefix, u8 plen)
Definition: util.c:18
vlib_node_registration_t lb4_nodeport_node
(constructor) VLIB_REGISTER_NODE (lb4_nodeport_node)
Definition: node.c:1204
clib_bihash_8_8_t mapping_by_as4
Definition: lb.h:554
static const char *const *const lb_dpo_gre4_nodes[DPO_PROTO_NUM]
Definition: lb.c:42
An node in the FIB graph.
Definition: fib_node.h:295
Definition: lb.h:167
vlib_main_t * vm
Definition: in2out_ed.c:1810
fib_node_t fib_node
Registration to FIB event.
Definition: lb.h:112
u16 port
Definition: lb.h:246
u8 src_ip_is_ipv6
Definition: lb.h:449
static_always_inline void vlib_refcount_add(vlib_refcount_t *r, u32 thread_index, u32 counter_index, i32 v)
Definition: refcount.h:68
format_function_t format_ip46_address
Definition: ip46_address.h:50
#define lb_hash_foreach_entry(h, bucket, i)
Definition: lbhash.h:72
ip46_address_t src_ip
for vip + port case, src_ip = vip; for node ip + node_port, src_ip = node_ip
Definition: lb.h:447
static const char *const lb_dpo_gre6_ip6[]
Definition: lb.c:49
u32 new_length
Definition: lb.h:579
static const dpo_vft_t lb_vft
Definition: load_balance.c:896
#define ip46_prefix_is_ip4(ip46, len)
Definition: util.h:27
#define pool_free(p)
Free a pool.
Definition: pool.h:412
static bool lb_vip_is_nat4_port(const lb_vip_t *vip)
Definition: lb.h:378
fib_node_index_t fib_table_entry_special_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags)
Add a &#39;special&#39; entry to the FIB.
Definition: fib_table.c:405
u64 value
the value
Definition: bihash_8_8.h:36
dpo_type_t dpo_l3dsr_port_type
Definition: lb.h:542
dpo_type_t dpo_nat4_port_type
Definition: lb.h:543
static const char *const lb_dpo_gre6_ip6_port[]
Definition: lb.c:65
format_function_t format_ip6_address
Definition: format.h:91
static int lb_vip_prefix_index_free(lb_main_t *lbm, u32 instance)
Definition: lb.c:878
dpo_type_t dpo_gre4_port_type
Definition: lb.h:539
u32 vrf_id
Definition: lb.h:458
#define lb_vip_is_ip6(type)
Definition: lb.h:340
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:342
static bool lb_vip_is_nat6_port(const lb_vip_t *vip)
Definition: lb.h:383
#define lb_foreach_vip_counter
Definition: lb.h:171
#define clib_warning(format, args...)
Definition: error.h:59
vlib_main_t * vlib_main
Definition: lb.h:568
fib_node_get_t fnv_get
Definition: fib_node.h:283
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
u32 as_index
Definition: lb.h:168
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:33
static fib_node_back_walk_rc_t lb_fib_node_back_walk_notify(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
Definition: lb.c:1321
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:186
dpo_type_t dpo_gre6_type
Definition: lb.h:538
u32 last_garbage_collection
Last time garbage collection was run to free the ASs.
Definition: lb.h:281
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
static_always_inline void lb_hash_free(lb_hash_t *h)
Definition: lbhash.h:100
lb_as_t * ass
Pool of ASs.
Definition: lb.h:487
uword * vip_index_by_nodeport
Definition: lb.h:497
ip6_address_t addr
Definition: lb.h:433
lb_vip_type_t type
The type of traffic for this.
Definition: lb.h:313
Context passed between object during a back walk.
Definition: fib_node.h:208
fib_node_index_t fib_table_entry_special_dpo_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Add a &#39;special&#39; entry to the FIB that links to the DPO passed A special entry is an entry that the FI...
Definition: fib_table.c:324
void vlib_validate_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
validate a simple counter
Definition: counter.c:79
u8 value
Definition: qos.api:54
#define ASSERT(truth)
static int lb_vip_port_find_diff_port(ip46_address_t *prefix, u8 plen, u8 protocol, u16 port, u32 *vip_index)
Definition: lb.c:547
int lb_vip_del_ass_withlock(u32 vip_index, ip46_address_t *addresses, u32 n, u8 flush)
Definition: lb.c:796
manual_print typedef address
Definition: ip_types.api:84
lb_vip_type_t
The load balancer supports IPv4 and IPv6 traffic and GRE4, GRE6, L3DSR and NAT4, NAT6 encap...
Definition: lb.h:208
manual_print typedef u8 ip6_address[16]
Definition: ip_types.api:19
u16 target_port
Definition: lb.h:457
int lb_vip_find_index(ip46_address_t *prefix, u8 plen, u8 protocol, u16 port, u32 *vip_index)
Definition: lb.c:554
u8 * format_lb_as(u8 *s, va_list *args)
Definition: lb.c:187
ip46_address_t prefix
Definition: lb.h:574
u32 new_flow_table_mask
New flows table length - 1 (length MUST be a power of 2)
Definition: lb.h:276
dpo_type_t dpo_gre6_port_type
Definition: lb.h:540
static const char *const *const lb_dpo_nat6_port_nodes[DPO_PROTO_NUM]
Definition: lb.c:91
static void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Clear a simple counter Clears the set of per-thread u16 counters, and the u64 counter.
Definition: counter.h:139
static fib_source_t lb_fib_src
Definition: lb.c:30
lb_vip_encap_args_t encap_args
Definition: lb.h:580
u32 vip_prefix_index
Definition: lb.h:307
lb_per_cpu_t * per_cpu
Some global data is per-cpu.
Definition: lb.h:502
static void lb_dpo_unlock(dpo_id_t *dpo)
Definition: lb.c:1267
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static uword is_pow2(uword x)
Definition: clib.h:235
u16 target_port
Definition: lb.h:233
u32 as_index
Definition: lb.c:274
vlib_simple_counter_main_t vip_counters[LB_N_VIP_COUNTERS]
Per VIP counter.
Definition: lb.h:532
int lb_nat6_interface_add_del(u32 sw_if_index, int is_del)
Definition: lb.c:1344
typedef key
Definition: ipsec_types.api:83
u64 as_u64
Definition: lb.h:250
int lb_vip_add(lb_vip_add_args_t args, u32 *vip_index)
Definition: lb.c:1046
static int lb_vip_port_find_index_with_lock(ip46_address_t *prefix, u8 plen, u8 protocol, u16 port, u32 *vip_index)
Definition: lb.c:530
static const char *const lb_dpo_gre4_ip6[]
Definition: lb.c:41
#define CLIB_SPINLOCK_ASSERT_LOCKED(_p)
Definition: lock.h:49
#define DPO_PROTO_NUM
Definition: dpo.h:70
#define LB_VIP_PER_PORT_BUCKETS
Definition: lb.h:51
ip6_address_t ip6_src_address
Source address used in IPv6 encapsulated traffic.
Definition: lb.h:512
u8 * format_lb_vip_detailed(u8 *s, va_list *args)
Definition: lb.c:195
vl_api_address_t ip
Definition: l2.api:490
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static fib_node_t * lb_fib_node_get_node(fib_node_index_t index)
Definition: lb.c:1270
u32 instance
Definition: gre.api:57
u64 uword
Definition: types.h:112
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:983
clib_spinlock_t writer_lock
Definition: lb.h:565
lb_snat_mapping_t * snat_mappings
Definition: lb.h:558
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:197
void lb_garbage_collection()
Definition: lb.c:357
static bool lb_vip_is_l3dsr_port(const lb_vip_t *vip)
Definition: lb.h:373
u16 port
Definition: lb_types.api:72
u8 protocol
Definition: lb.h:247
u16 port
Definition: lb.h:434
u32 next_hop_child_index
The child index on the FIB entry.
Definition: lb.h:156
dpo_type_t dpo_l3dsr_type
Definition: lb.h:541
#define hash_get_mem(h, key)
Definition: hash.h:269
A FIB graph nodes virtual function table.
Definition: fib_node.h:282
u32 fib_index
Definition: lb.h:459
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
clib_bihash_8_8_t vip_index_per_port
Definition: lb.h:551
static int lb_vip_add_port_filter(lb_main_t *lbm, lb_vip_t *vip, u32 vip_prefix_index, u32 vip_idx)
Add the VIP filter entry.
Definition: lb.c:963
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:232
#define vec_foreach(var, vec)
Vector iterator.
u16 protocol
Definition: lb.h:435
dpo_id_t dpo
The next DPO in the graph to follow.
Definition: lb.h:161
static const char *const lb_dpo_l3dsr_ip4[]
Definition: lb.c:72
static const char *const lb_dpo_gre4_ip4_port[]
Definition: lb.c:56
u8 flags
Some per-AS flags.
Definition: lb.h:133
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:182
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
Definition: udp_local.c:471
ip4_address_t addr
Definition: lb.h:418
clib_bihash_24_8_t mapping_by_as6
Definition: lb.h:555
lb_new_flow_entry_t * new_flow_table
Vector mapping (flow-hash & new_connect_table_mask) to AS index.
Definition: lb.h:270
static const char *const *const lb_dpo_l3dsr_nodes[DPO_PROTO_NUM]
Definition: lb.c:73
dpo_type_t dpo_nat6_port_type
Definition: lb.h:544
static uword clib_bitmap_first_clear(uword *ai)
Return the lowest numbered clear bit in a bitmap.
Definition: bitmap.h:445
u8 flags
Flags related to this VIP.
Definition: lb.h:325
lb_vip_type_t type
Definition: lb.h:578
static const char *const *const lb_dpo_gre6_port_nodes[DPO_PROTO_NUM]
Definition: lb.c:66
static char * lb_vip_type_strings[]
Definition: lb.c:124
u8 * format_lb_dpo(u8 *s, va_list *va)
Definition: lb.c:1257
ip46_address_t as_ip
Definition: lb.h:448
Load balancing service is provided per VIP+protocol+port.
Definition: lb.h:262
u32 * as_indexes
Pool of AS indexes used for this VIP.
Definition: lb.h:332
u16 fib_index
Definition: lb.h:420
#define lb_hash_size(h)
Definition: lbhash.h:65
u8 rsv
Definition: lb.h:248
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:304
ip46_type_t
Definition: ip46_address.h:22
void dpo_stack(dpo_type_t child_type, dpo_proto_t child_proto, dpo_id_t *dpo, const dpo_id_t *parent)
Stack one DPO object on another, and thus establish a child-parent relationship.
Definition: dpo.c:516
#define lb_put_writer_lock()
Definition: lb.c:35
fib_node_index_t next_hop_fib_entry_index
The FIB entry index for the next-hop.
Definition: lb.h:151
static_always_inline u32 lb_hash_elts(lb_hash_t *h, u32 time_now)
Definition: lbhash.h:186
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128