X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fl2%2Fl2_fib.c;h=959cf4dea17ee8ab7d6606a915b5f6842e320d74;hb=7dbd7265daf6fa0f522870586036c89a99bc4958;hp=9f4c823f67b32c567f31b877ab5dd848e9fdcab5;hpb=e531f4cb5766fbf27e7a8af8e19ccf667b53852b;p=vpp.git diff --git a/src/vnet/l2/l2_fib.c b/src/vnet/l2/l2_fib.c index 9f4c823f67b..959cf4dea17 100644 --- a/src/vnet/l2/l2_fib.c +++ b/src/vnet/l2/l2_fib.c @@ -54,6 +54,17 @@ l2fib_main_t l2fib_main; +static void +incr_mac_address (u8 * mac) +{ + u64 tmp = *((u64 *) mac); + tmp = clib_net_to_host_u64 (tmp); + tmp += 1 << 16; /* skip unused (least significant) octets */ + tmp = clib_host_to_net_u64 (tmp); + + clib_memcpy (mac, &tmp, 6); +} + /** Format sw_if_index. If the value is ~0, use the text "N/A" */ u8 * format_vnet_sw_if_index_name_with_NA (u8 * s, va_list * args) @@ -129,35 +140,52 @@ show_l2fib (vlib_main_t * vm, u8 verbose = 0; u8 raw = 0; u8 learn = 0; + u8 add = 0; u32 bd_id, bd_index = ~0; u8 now = (u8) (vlib_time_now (vm) / 60); u8 *s = 0; - if (unformat (input, "raw")) - raw = 1; - else if (unformat (input, "verbose")) - verbose = 1; - else if (unformat (input, "bd_index %d", &bd_index)) - verbose = 1; - else if (unformat (input, "learn")) - { - learn = 1; - verbose = 0; - } - else if (unformat (input, "bd_id %d", &bd_id)) + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - uword *p = hash_get (bdm->bd_index_by_bd_id, bd_id); - if (p) + if (unformat (input, "raw")) { - if (learn == 0) - verbose = 1; - bd_index = p[0]; + raw = 1; + verbose = 0; + break; } - else + else if (unformat (input, "verbose")) + verbose = 1; + else if (unformat (input, "all")) + verbose = 1; + else if (unformat (input, "bd_index %d", &bd_index)) + verbose = 1; + else if (unformat (input, "learn")) + { + add = 0; + learn = 1; + verbose = 1; + } + else if (unformat (input, "add")) { - vlib_cli_output (vm, "no such bridge domain id"); - return 0; + learn = 0; + add = 1; + verbose = 1; } + else if (unformat (input, "bd_id %d", &bd_id)) + { + uword *p = hash_get (bdm->bd_index_by_bd_id, bd_id); + if (p) + { + verbose = 1; + bd_index = p[0]; + } + else + return clib_error_return (0, + "bridge domain id %d doesn't exist\n", + bd_id); + } + else + break; } for (i = 0; i < h->nbuckets; i++) @@ -173,7 +201,7 @@ show_l2fib (vlib_main_t * vm, if (v->kvp[k].key == ~0ULL && v->kvp[k].value == ~0ULL) continue; - if ((verbose || learn) && first_entry) + if (verbose && first_entry) { first_entry = 0; vlib_cli_output (vm, @@ -185,27 +213,30 @@ show_l2fib (vlib_main_t * vm, key.raw = v->kvp[k].key; result.raw = v->kvp[k].value; + total_entries++; - if ((verbose || learn) - & ((bd_index >> 31) || (bd_index == key.fields.bd_index))) + if (verbose && + ((bd_index >> 31) || (bd_index == key.fields.bd_index))) { if (learn && result.fields.age_not) - { - total_entries++; - continue; /* skip provisioned macs */ - } + continue; /* skip provisioned macs */ + + if (add && !result.fields.age_not) + continue; /* skip learned macs */ bd_config = vec_elt_at_index (l2input_main.bd_configs, key.fields.bd_index); - if (bd_config->mac_age && !result.fields.age_not) + if (result.fields.age_not) + s = format (s, "no"); + else if (bd_config->mac_age == 0) + s = format (s, "-"); + else { i16 delta = now - result.fields.timestamp; delta += delta < 0 ? 256 : 0; s = format (s, "%d", delta); } - else - s = format (s, "-"); vlib_cli_output (vm, "%=19U%=7d%=7d %3d/%-3d%=9v%=7s%=7s%=5s%=30U", @@ -221,7 +252,6 @@ show_l2fib (vlib_main_t * vm, msm->vnet_main, result.fields.sw_if_index); vec_reset_length (s); } - total_entries++; } v++; } @@ -265,7 +295,7 @@ show_l2fib (vlib_main_t * vm, * @cliexend * Example of how to display all the MAC Address entries in the L2 * FIB table: - * @cliexstart{show l2fib verbose} + * @cliexstart{show l2fib all} * Mac Address BD Idx Interface Index static filter bvi refresh timestamp * 52:54:00:53:18:33 1 GigabitEthernet0/8/0.200 3 0 0 0 0 0 * 52:54:00:53:18:55 1 GigabitEthernet0/8/0.200 3 1 0 0 0 0 @@ -276,7 +306,7 @@ show_l2fib (vlib_main_t * vm, /* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_l2fib_cli, static) = { .path = "show l2fib", - .short_help = "show l2fib [verbose | learn | bd_id | bd_index | raw", + .short_help = "show l2fib [all] | [bd_id | bd_index ] [learn | add] | [raw]", .function = show_l2fib, }; /* *INDENT-ON* */ @@ -342,7 +372,7 @@ l2fib_cur_seq_num (u32 bd_index, u32 sw_if_index) * If the entry already exists then overwrite it */ void -l2fib_add_entry (u64 mac, u32 bd_index, +l2fib_add_entry (u8 * mac, u32 bd_index, u32 sw_if_index, u8 static_mac, u8 filter_mac, u8 bvi_mac) { l2fib_entry_key_t key; @@ -353,7 +383,7 @@ l2fib_add_entry (u64 mac, u32 bd_index, BVT (clib_bihash_kv) kv; /* set up key */ - key.raw = l2fib_make_key ((u8 *) & mac, bd_index); + key.raw = l2fib_make_key (mac, bd_index); /* check if entry alread exist */ if (BV (clib_bihash_search) (&fm->mac_table, &kv, &kv)) @@ -392,16 +422,15 @@ l2fib_add (vlib_main_t * vm, bd_main_t *bdm = &bd_main; vnet_main_t *vnm = vnet_get_main (); clib_error_t *error = 0; - u64 mac; + u8 mac[6]; u32 bd_id; u32 bd_index; u32 sw_if_index = ~0; - u32 filter_mac = 0; u32 static_mac = 0; u32 bvi_mac = 0; uword *p; - if (!unformat_user (input, unformat_ethernet_address, &mac)) + if (!unformat (input, "%U", unformat_ethernet_address, mac)) { error = clib_error_return (0, "expected mac address `%U'", format_unformat_error, input); @@ -425,29 +454,25 @@ l2fib_add (vlib_main_t * vm, if (unformat (input, "filter")) { - filter_mac = 1; - static_mac = 1; - + l2fib_add_filter_entry (mac, bd_index); + return 0; } - else + + if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index)) { + error = clib_error_return (0, "unknown interface `%U'", + format_unformat_error, input); + goto done; + } - if (!unformat_user - (input, unformat_vnet_sw_interface, vnm, &sw_if_index)) - { - error = clib_error_return (0, "unknown interface `%U'", - format_unformat_error, input); - goto done; - } - if (unformat (input, "static")) - { - static_mac = 1; - } - else if (unformat (input, "bvi")) - { - bvi_mac = 1; - static_mac = 1; - } + if (unformat (input, "static")) + { + static_mac = 1; + } + else if (unformat (input, "bvi")) + { + bvi_mac = 1; + static_mac = 1; } if (vec_len (l2input_main.configs) <= sw_if_index) @@ -457,10 +482,7 @@ l2fib_add (vlib_main_t * vm, goto done; } - if (filter_mac) - l2fib_add_filter_entry (mac, bd_index); - else - l2fib_add_fwd_entry (mac, bd_index, sw_if_index, static_mac, bvi_mac); + l2fib_add_fwd_entry (mac, bd_index, sw_if_index, static_mac, bvi_mac); done: return error; @@ -507,7 +529,7 @@ l2fib_test_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { clib_error_t *error = 0; - u64 mac, save_mac; + u8 mac[6], save_mac[6]; u32 bd_index = 0; u32 sw_if_index = 8; u32 bvi_mac = 0; @@ -520,7 +542,7 @@ l2fib_test_command_fn (vlib_main_t * vm, while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat (input, "mac %U", unformat_ethernet_address, &mac)) + if (unformat (input, "mac %U", unformat_ethernet_address, mac)) mac_set = 1; else if (unformat (input, "add")) is_add = 1; @@ -541,19 +563,14 @@ l2fib_test_command_fn (vlib_main_t * vm, return clib_error_return (0, "noop: pick at least one of (add,del,check)"); - save_mac = mac; + clib_memcpy (save_mac, mac, 6); if (is_add) { for (i = 0; i < count; i++) { - u64 tmp; - l2fib_add_fwd_entry (mac, bd_index, sw_if_index, mac, bvi_mac); - tmp = clib_net_to_host_u64 (mac); - tmp >>= 16; - tmp++; - tmp <<= 16; - mac = clib_host_to_net_u64 (tmp); + l2fib_add_fwd_entry (mac, bd_index, sw_if_index, *mac, bvi_mac); + incr_mac_address (mac); } } @@ -562,38 +579,28 @@ l2fib_test_command_fn (vlib_main_t * vm, BVT (clib_bihash_kv) kv; l2fib_main_t *mp = &l2fib_main; - mac = save_mac; + clib_memcpy (mac, save_mac, 6); for (i = 0; i < count; i++) { - u64 tmp; - kv.key = l2fib_make_key ((u8 *) & mac, bd_index); + kv.key = l2fib_make_key (mac, bd_index); if (BV (clib_bihash_search) (&mp->mac_table, &kv, &kv)) { - clib_warning ("key %U AWOL", format_ethernet_address, &mac); + clib_warning ("key %U AWOL", format_ethernet_address, mac); break; } - tmp = clib_net_to_host_u64 (mac); - tmp >>= 16; - tmp++; - tmp <<= 16; - mac = clib_host_to_net_u64 (tmp); + incr_mac_address (mac); } } if (is_del) { + clib_memcpy (mac, save_mac, 6); + for (i = 0; i < count; i++) { - u64 tmp; - - l2fib_del_entry (mac, bd_index); - - tmp = clib_net_to_host_u64 (mac); - tmp >>= 16; - tmp++; - tmp <<= 16; - mac = clib_host_to_net_u64 (tmp); + l2fib_del_entry (mac, bd_index, 0); + incr_mac_address (mac); } } @@ -648,24 +655,28 @@ VLIB_CLI_COMMAND (l2fib_test_command, static) = { /** * Delete an entry from the l2fib. - * Return 0 if the entry was deleted, or 1 if it was not found + * Return 0 if the entry was deleted, or 1 it was not found or if + * sw_if_index is non-zero and does not match that in the entry. */ -static u32 -l2fib_del_entry_by_key (u64 raw_key) +u32 +l2fib_del_entry (u8 * mac, u32 bd_index, u32 sw_if_index) { - l2fib_entry_result_t result; l2fib_main_t *mp = &l2fib_main; BVT (clib_bihash_kv) kv; /* set up key */ - kv.key = raw_key; + kv.key = l2fib_make_key (mac, bd_index); if (BV (clib_bihash_search) (&mp->mac_table, &kv, &kv)) return 1; result.raw = kv.value; + /* check if sw_if_index of entry match */ + if ((sw_if_index != 0) && (sw_if_index != result.fields.sw_if_index)) + return 1; + /* decrement counter if dynamically learned mac */ if ((result.fields.age_not == 0) && (l2learn_main.global_learn_count)) l2learn_main.global_learn_count--; @@ -675,16 +686,6 @@ l2fib_del_entry_by_key (u64 raw_key) return 0; } -/** - * Delete an entry from the l2fib. - * Return 0 if the entry was deleted, or 1 if it was not found - */ -u32 -l2fib_del_entry (u64 mac, u32 bd_index) -{ - return l2fib_del_entry_by_key (l2fib_make_key ((u8 *) & mac, bd_index)); -} - /** * Delete an entry from the L2FIB. * The CLI format is: @@ -696,12 +697,12 @@ l2fib_del (vlib_main_t * vm, { bd_main_t *bdm = &bd_main; clib_error_t *error = 0; - u64 mac; + u8 mac[6]; u32 bd_id; u32 bd_index; uword *p; - if (!unformat_user (input, unformat_ethernet_address, &mac)) + if (!unformat (input, "%U", unformat_ethernet_address, mac)) { error = clib_error_return (0, "expected mac address `%U'", format_unformat_error, input); @@ -724,7 +725,7 @@ l2fib_del (vlib_main_t * vm, bd_index = p[0]; /* Delete the entry */ - if (l2fib_del_entry (mac, bd_index)) + if (l2fib_del_entry (mac, bd_index, 0)) { error = clib_error_return (0, "mac entry not found"); goto done; @@ -745,7 +746,7 @@ done: /* *INDENT-OFF* */ VLIB_CLI_COMMAND (l2fib_del_cli, static) = { .path = "l2fib del", - .short_help = "l2fib del ", + .short_help = "l2fib del []", .function = l2fib_del, }; /* *INDENT-ON* */ @@ -756,17 +757,21 @@ VLIB_CLI_COMMAND (l2fib_del_cli, static) = { void l2fib_start_ager_scan (vlib_main_t * vm) { - l2_bridge_domain_t *bd_config; - int enable = 0; + uword evt = L2_MAC_AGE_PROCESS_EVENT_ONE_PASS; /* check if there is at least one bd with mac aging enabled */ + l2_bridge_domain_t *bd_config; vec_foreach (bd_config, l2input_main.bd_configs) + { if (bd_config->bd_id != ~0 && bd_config->mac_age != 0) - enable = 1; + { + evt = L2_MAC_AGE_PROCESS_EVENT_START; + break; + } + } vlib_process_signal_event (vm, l2fib_mac_age_scanner_process_node.index, - enable ? L2_MAC_AGE_PROCESS_EVENT_START : - L2_MAC_AGE_PROCESS_EVENT_ONE_PASS, 0); + evt, 0); } /** @@ -970,12 +975,12 @@ l2fib_scan (vlib_main_t * vm, f64 start_time, u8 event_only) u32 client = lm->client_pid; u32 cl_idx = lm->client_index; vl_api_l2_macs_event_t *mp = 0; - unix_shared_memory_queue_t *q = 0; + vl_api_registration_t *reg = 0; if (client) { mp = allocate_mac_evt_buf (client, cl_idx); - q = vl_api_client_index_to_input_queue (lm->client_index); + reg = vl_api_client_index_to_registration (lm->client_index); } for (i = 0; i < h->nbuckets; i++) @@ -1019,35 +1024,39 @@ l2fib_scan (vlib_main_t * vm, f64 start_time, u8 event_only) if (result.fields.age_not == 0) learn_count++; - if (PREDICT_FALSE (evt_idx >= fm->max_macs_in_event)) + if (client) { - /* event message full, send it and start a new one */ - if (q && (q->cursize < q->maxsize)) - { - mp->n_macs = htonl (evt_idx); - vl_msg_api_send_shmem (q, (u8 *) & mp); - mp = allocate_mac_evt_buf (client, cl_idx); - } - else + if (PREDICT_FALSE (evt_idx >= fm->max_macs_in_event)) { - clib_warning ("MAC event to pid %d queue stuffed!" - " %d MAC entries lost", client, evt_idx); + /* event message full, send it and start a new one */ + if (reg && vl_api_can_send_msg (reg)) + { + mp->n_macs = htonl (evt_idx); + vl_api_send_msg (reg, (u8 *) mp); + mp = allocate_mac_evt_buf (client, cl_idx); + } + else + { + if (reg) + clib_warning ("MAC event to pid %d queue stuffed!" + " %d MAC entries lost", client, + evt_idx); + } + evt_idx = 0; } - evt_idx = 0; - } - if (client) - { if (result.fields.lrn_evt) { /* copy mac entry to event msg */ clib_memcpy (mp->mac[evt_idx].mac_addr, key.fields.mac, 6); - mp->mac[evt_idx].is_del = 0; + mp->mac[evt_idx].action = result.fields.lrn_mov ? + MAC_EVENT_ACTION_MOVE : MAC_EVENT_ACTION_ADD; mp->mac[evt_idx].sw_if_index = htonl (result.fields.sw_if_index); - /* clear event bit and update mac entry */ + /* clear event bits and update mac entry */ result.fields.lrn_evt = 0; + result.fields.lrn_mov = 0; BVT (clib_bihash_kv) kv; kv.key = key.raw; kv.value = result.raw; @@ -1084,7 +1093,7 @@ l2fib_scan (vlib_main_t * vm, f64 start_time, u8 event_only) { /* copy mac entry to event msg */ clib_memcpy (mp->mac[evt_idx].mac_addr, key.fields.mac, 6); - mp->mac[evt_idx].is_del = 1; + mp->mac[evt_idx].action = MAC_EVENT_ACTION_DELETE; mp->mac[evt_idx].sw_if_index = htonl (result.fields.sw_if_index); evt_idx++; @@ -1107,15 +1116,16 @@ l2fib_scan (vlib_main_t * vm, f64 start_time, u8 event_only) /* send any outstanding mac event message else free message buffer */ if (evt_idx) { - if (q && (q->cursize < q->maxsize)) + if (reg && vl_api_can_send_msg (reg)) { mp->n_macs = htonl (evt_idx); - vl_msg_api_send_shmem (q, (u8 *) & mp); + vl_api_send_msg (reg, (u8 *) mp); } else { - clib_warning ("MAC event to pid %d queue stuffed!" - " %d MAC entries lost", client, evt_idx); + if (reg) + clib_warning ("MAC event to pid %d queue stuffed!" + " %d MAC entries lost", client, evt_idx); vl_msg_api_free (mp); } } @@ -1125,13 +1135,6 @@ l2fib_scan (vlib_main_t * vm, f64 start_time, u8 event_only) return delta_t + accum_t; } -/* Type of scan */ -#define SCAN_MAC_AGE 0 -#define SCAN_MAC_EVENT 1 - -/* Maximum f64 value */ -#define TIME_MAX (1.7976931348623157e+308) - static uword l2fib_mac_age_scanner_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) @@ -1140,22 +1143,16 @@ l2fib_mac_age_scanner_process (vlib_main_t * vm, vlib_node_runtime_t * rt, l2fib_main_t *fm = &l2fib_main; l2learn_main_t *lm = &l2learn_main; bool enabled = 0; - bool scan = SCAN_MAC_AGE; /* SCAN_FOR_AGE or SCAN_FOR_EVENT */ - f64 start_time, next_age_scan_time = TIME_MAX; + f64 start_time, next_age_scan_time = CLIB_TIME_MAX; while (1) { - if (enabled) + if (lm->client_pid) + vlib_process_wait_for_event_or_clock (vm, fm->event_scan_delay); + else if (enabled) { - if (lm->client_pid) /* mac event client waiting */ - vlib_process_wait_for_event_or_clock (vm, fm->event_scan_delay); - else /* agin only */ - { - f64 t = next_age_scan_time - vlib_time_now (vm); - if (t < fm->event_scan_delay) - t = fm->event_scan_delay; - vlib_process_wait_for_event_or_clock (vm, t); - } + f64 t = next_age_scan_time - vlib_time_now (vm); + vlib_process_wait_for_event_or_clock (vm, t); } else vlib_process_wait_for_event (vm); @@ -1164,41 +1161,26 @@ l2fib_mac_age_scanner_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vec_reset_length (event_data); start_time = vlib_time_now (vm); + enum + { SCAN_MAC_AGE, SCAN_MAC_EVENT, SCAN_DISABLE } scan = SCAN_MAC_AGE; switch (event_type) { case ~0: /* timer expired */ - if ((lm->client_pid == 0) || (start_time >= next_age_scan_time)) - { - scan = SCAN_MAC_AGE; - if (enabled) - next_age_scan_time = start_time + L2FIB_AGE_SCAN_INTERVAL; - else - next_age_scan_time = TIME_MAX; - } - else + if (lm->client_pid != 0 && start_time < next_age_scan_time) scan = SCAN_MAC_EVENT; break; case L2_MAC_AGE_PROCESS_EVENT_START: - scan = SCAN_MAC_AGE; - next_age_scan_time = start_time + L2FIB_AGE_SCAN_INTERVAL; enabled = 1; break; case L2_MAC_AGE_PROCESS_EVENT_STOP: enabled = 0; - next_age_scan_time = TIME_MAX; - l2fib_main.age_scan_duration = 0; - l2fib_main.evt_scan_duration = 0; - continue; + scan = SCAN_DISABLE; + break; case L2_MAC_AGE_PROCESS_EVENT_ONE_PASS: - scan = SCAN_MAC_AGE; - if (enabled) - next_age_scan_time = start_time + L2FIB_AGE_SCAN_INTERVAL; - else - next_age_scan_time = TIME_MAX; break; default: @@ -1208,7 +1190,20 @@ l2fib_mac_age_scanner_process (vlib_main_t * vm, vlib_node_runtime_t * rt, if (scan == SCAN_MAC_EVENT) l2fib_main.evt_scan_duration = l2fib_scan (vm, start_time, 1); else - l2fib_main.age_scan_duration = l2fib_scan (vm, start_time, 0); + { + if (scan == SCAN_MAC_AGE) + l2fib_main.age_scan_duration = l2fib_scan (vm, start_time, 0); + if (scan == SCAN_DISABLE) + { + l2fib_main.age_scan_duration = 0; + l2fib_main.evt_scan_duration = 0; + } + /* schedule next scan */ + if (enabled) + next_age_scan_time = start_time + L2FIB_AGE_SCAN_INTERVAL; + else + next_age_scan_time = CLIB_TIME_MAX; + } } return 0; }