From 32e1c010b0c34fd0984f7fc45fae648a182025c5 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Tue, 22 Nov 2016 17:07:28 +0000 Subject: IP Multicast FIB (mfib) - IPv[46] mfib tables with support for (*,G/m), (*,G) and (S,G) exact and longest prefix match - Replication represented via a new replicate DPO. - RPF configuration and data-plane checking - data-plane signals sent to listening control planes. The functions of multicast forwarding entries differ from their unicast conterparts, so we introduce a new mfib_table_t and mfib_entry_t objects. However, we re-use the fib_path_list to resolve and build the entry's output list. the fib_path_list provides the service to construct a replicate DPO for multicast. 'make tests' is added to with two new suites; TEST=mfib, this is invocation of the CLI command 'test mfib' which deals with many path add/remove, flag set/unset scenarios, TEST=ip-mcast, data-plane forwarding tests. Updated applications to use the new MIFB functions; - IPv6 NS/RA. - DHCPv6 unit tests for these are undated accordingly. Change-Id: I49ec37b01f1b170335a5697541c8fd30e6d3a961 Signed-off-by: Neale Ranns --- src/vnet/mfib/mfib_signal.c | 201 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 src/vnet/mfib/mfib_signal.c (limited to 'src/vnet/mfib/mfib_signal.c') diff --git a/src/vnet/mfib/mfib_signal.c b/src/vnet/mfib/mfib_signal.c new file mode 100644 index 00000000..9f6205de --- /dev/null +++ b/src/vnet/mfib/mfib_signal.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include + +/** + * @brief Pool of signals + */ +static mfib_signal_t *mfib_signal_pool; + +/** + * @brief pool of dlist elements + */ +static dlist_elt_t *mfib_signal_dlist_pool; + +/** + * the list/set of interfaces with signals pending + */ +typedef struct mfib_signal_q_t_ +{ + /** + * the dlist indext that is the head of the list + */ + u32 mip_head; + + /** + * Spin lock to protect the list + */ + int mip_lock; +} mfib_signal_q_t; + +/** + * @brief The pending queue of signals to deliver to the control plane + */ +static mfib_signal_q_t mfib_signal_pending ; + +static void +mfib_signal_list_init (void) +{ + dlist_elt_t *head; + u32 hi; + + pool_get(mfib_signal_dlist_pool, head); + hi = head - mfib_signal_dlist_pool; + + mfib_signal_pending.mip_head = hi; + clib_dlist_init(mfib_signal_dlist_pool, hi); +} + +void +mfib_signal_module_init (void) +{ + mfib_signal_list_init(); +} + +int +mfib_signal_send_one (struct _unix_shared_memory_queue *q, + u32 context) +{ + u32 li, si; + + /* + * with the lock held, pop a signal from the q. + */ + while (__sync_lock_test_and_set (&mfib_signal_pending.mip_lock, 1)) + ; + { + li = clib_dlist_remove_head(mfib_signal_dlist_pool, + mfib_signal_pending.mip_head); + } + mfib_signal_pending.mip_lock = 0; + + if (~0 != li) + { + mfib_signal_t *mfs; + mfib_itf_t *mfi; + dlist_elt_t *elt; + + elt = pool_elt_at_index(mfib_signal_dlist_pool, li); + si = elt->value; + + mfs = pool_elt_at_index(mfib_signal_pool, si); + mfi = mfib_itf_get(mfs->mfs_itf); + mfi->mfi_si = INDEX_INVALID; + __sync_fetch_and_and(&mfi->mfi_flags, + ~MFIB_ITF_FLAG_SIGNAL_PRESENT); + + + vl_mfib_signal_send_one(q, context, mfs); + + /* + * with the lock held, return the resoruces of the signals posted + */ + while (__sync_lock_test_and_set(&mfib_signal_pending.mip_lock, 1)) + ; + { + pool_put_index(mfib_signal_pool, si); + pool_put_index(mfib_signal_dlist_pool, li); + } + mfib_signal_pending.mip_lock = 0; + + return (1); + } + return (0); +} + +void +mfib_signal_push (const mfib_entry_t *mfe, + mfib_itf_t *mfi, + vlib_buffer_t *b0) +{ + mfib_signal_t *mfs; + dlist_elt_t *elt; + u32 si, li; + + while (__sync_lock_test_and_set (&mfib_signal_pending.mip_lock, 1)) + ; + { + pool_get(mfib_signal_pool, mfs); + pool_get(mfib_signal_dlist_pool, elt); + + si = mfs - mfib_signal_pool; + li = elt - mfib_signal_dlist_pool; + + elt->value = si; + mfi->mfi_si = li; + + clib_dlist_addhead(mfib_signal_dlist_pool, + mfib_signal_pending.mip_head, + li); + } + mfib_signal_pending.mip_lock = 0; + + mfs->mfs_entry = mfib_entry_get_index(mfe); + mfs->mfs_itf = mfib_itf_get_index(mfi); + + if (NULL != b0) + { + mfs->mfs_buffer_len = b0->current_length; + memcpy(mfs->mfs_buffer, + vlib_buffer_get_current(b0), + (mfs->mfs_buffer_len > MFIB_SIGNAL_BUFFER_SIZE ? + MFIB_SIGNAL_BUFFER_SIZE : + mfs->mfs_buffer_len)); + } + else + { + mfs->mfs_buffer_len = 0; + } +} + +void +mfib_signal_remove_itf (const mfib_itf_t *mfi) +{ + u32 li; + + /* + * lock the queue to prevent further additions while we fiddle. + */ + li = mfi->mfi_si; + + if (INDEX_INVALID != li) + { + /* + * it's in the pending q + */ + while (__sync_lock_test_and_set (&mfib_signal_pending.mip_lock, 1)) + ; + { + dlist_elt_t *elt; + + /* + * with the lock held; + * - remove the signal from the pending list + * - free up the signal and list entry obejcts + */ + clib_dlist_remove(mfib_signal_dlist_pool, li); + + elt = pool_elt_at_index(mfib_signal_dlist_pool, li); + pool_put_index(mfib_signal_pool, elt->value); + pool_put(mfib_signal_dlist_pool, elt); + } + + mfib_signal_pending.mip_lock = 0; + } +} -- cgit 1.2.3-korg From 05b2bf2e31a90d97425230dcbf2bca6df54519ff Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Mon, 30 Jan 2017 06:44:58 -0800 Subject: MFIB Coverity warnings. The lock macro is functionally equivalent but more expressive (and might appease coverity) Change-Id: Ie3c9b2896a487a0302903bfbdd6348f6f091c67d Signed-off-by: Neale Ranns --- src/vat/api_format.c | 8 +++---- src/vnet/mfib/mfib_signal.c | 55 ++++++++++++++++++++++++++++----------------- src/vnet/mfib/mfib_test.c | 10 +++++---- 3 files changed, 44 insertions(+), 29 deletions(-) (limited to 'src/vnet/mfib/mfib_signal.c') diff --git a/src/vat/api_format.c b/src/vat/api_format.c index d4834b70..26df1aff 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -6706,9 +6706,6 @@ api_ip_mroute_add_del (vat_main_t * vam) S; /* Wait for a reply... */ W; - - /* Return the good/bad news */ - return (vam->retval); } static int @@ -16546,7 +16543,10 @@ static void vat_json_object_add_uint (node, "src-if-index", sw_if_index_from); vat_json_object_add_string_copy (node, "src-if-name", sw_if_from_name); vat_json_object_add_uint (node, "dst-if-index", sw_if_index_to); - vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name); + if (0 != sw_if_to_name) + { + vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name); + } vat_json_object_add_uint (node, "state", mp->state); } diff --git a/src/vnet/mfib/mfib_signal.c b/src/vnet/mfib/mfib_signal.c index 9f6205de..cd486da3 100644 --- a/src/vnet/mfib/mfib_signal.c +++ b/src/vnet/mfib/mfib_signal.c @@ -68,6 +68,28 @@ mfib_signal_module_init (void) mfib_signal_list_init(); } +static inline void +mfib_signal_lock_aquire (void) +{ + while (__sync_lock_test_and_set (&mfib_signal_pending.mip_lock, 1)) + ; +} + +static inline void +mfib_signal_lock_release (void) +{ + mfib_signal_pending.mip_lock = 0; +} + +#define MFIB_SIGNAL_CRITICAL_SECTION(_body) \ +{ \ + mfib_signal_lock_aquire(); \ + do { \ + _body; \ + } while (0); \ + mfib_signal_lock_release(); \ +} + int mfib_signal_send_one (struct _unix_shared_memory_queue *q, u32 context) @@ -77,13 +99,11 @@ mfib_signal_send_one (struct _unix_shared_memory_queue *q, /* * with the lock held, pop a signal from the q. */ - while (__sync_lock_test_and_set (&mfib_signal_pending.mip_lock, 1)) - ; - { + MFIB_SIGNAL_CRITICAL_SECTION( + ({ li = clib_dlist_remove_head(mfib_signal_dlist_pool, mfib_signal_pending.mip_head); - } - mfib_signal_pending.mip_lock = 0; + })); if (~0 != li) { @@ -106,13 +126,11 @@ mfib_signal_send_one (struct _unix_shared_memory_queue *q, /* * with the lock held, return the resoruces of the signals posted */ - while (__sync_lock_test_and_set(&mfib_signal_pending.mip_lock, 1)) - ; - { + MFIB_SIGNAL_CRITICAL_SECTION( + ({ pool_put_index(mfib_signal_pool, si); pool_put_index(mfib_signal_dlist_pool, li); - } - mfib_signal_pending.mip_lock = 0; + })); return (1); } @@ -128,9 +146,8 @@ mfib_signal_push (const mfib_entry_t *mfe, dlist_elt_t *elt; u32 si, li; - while (__sync_lock_test_and_set (&mfib_signal_pending.mip_lock, 1)) - ; - { + MFIB_SIGNAL_CRITICAL_SECTION( + ({ pool_get(mfib_signal_pool, mfs); pool_get(mfib_signal_dlist_pool, elt); @@ -143,8 +160,7 @@ mfib_signal_push (const mfib_entry_t *mfe, clib_dlist_addhead(mfib_signal_dlist_pool, mfib_signal_pending.mip_head, li); - } - mfib_signal_pending.mip_lock = 0; + })); mfs->mfs_entry = mfib_entry_get_index(mfe); mfs->mfs_itf = mfib_itf_get_index(mfi); @@ -179,9 +195,8 @@ mfib_signal_remove_itf (const mfib_itf_t *mfi) /* * it's in the pending q */ - while (__sync_lock_test_and_set (&mfib_signal_pending.mip_lock, 1)) - ; - { + MFIB_SIGNAL_CRITICAL_SECTION( + ({ dlist_elt_t *elt; /* @@ -194,8 +209,6 @@ mfib_signal_remove_itf (const mfib_itf_t *mfi) elt = pool_elt_at_index(mfib_signal_dlist_pool, li); pool_put_index(mfib_signal_pool, elt->value); pool_put(mfib_signal_dlist_pool, elt); - } - - mfib_signal_pending.mip_lock = 0; + })); } } diff --git a/src/vnet/mfib/mfib_test.c b/src/vnet/mfib/mfib_test.c index 8735bfa7..8082a6bb 100644 --- a/src/vnet/mfib/mfib_test.c +++ b/src/vnet/mfib/mfib_test.c @@ -235,6 +235,7 @@ mfib_test_entry (fib_node_index_t fei, const replicate_t *rep; mfib_prefix_t pfx; va_list ap; + int res; va_start(ap, n_buckets); @@ -253,12 +254,11 @@ mfib_test_entry (fib_node_index_t fei, "%U links to %U", format_mfib_prefix, &pfx, format_dpo_id, &mfe->mfe_rep, 0); - return (!0); + res = !0; } else { dpo_id_t tmp = DPO_INVALID; - int res; mfib_entry_contribute_forwarding( fei, @@ -274,9 +274,11 @@ mfib_test_entry (fib_node_index_t fei, res = mfib_test_validate_rep_v(rep, n_buckets, ap); dpo_reset(&tmp); - - return (res); } + + va_end(ap); + + return (res); } static int -- cgit 1.2.3-korg