summaryrefslogtreecommitdiffstats
path: root/src/vnet/mfib/mfib_entry_src.c
blob: ca5c788a5460470367d2f2cba196aea5e71d0391 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
 * Copyright (c) 2018 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 <vnet/mfib/mfib_entry_src.h>

static mfib_entry_src_vft mfib_entry_src_vfts[MFIB_N_SOURCES];

static void
mfib_entry_src_default_deactiviate (mfib_entry_t *mfib_entry,
                                    mfib_entry_src_t *msrc)
{
}

static void
mfib_entry_src_default_activiate (mfib_entry_t *mfib_entry,
                                  mfib_entry_src_t *msrc)
{
}

static mfib_src_res_t
mfib_entry_src_default_cover_change (mfib_entry_t *mfib_entry,
                                     mfib_entry_src_t *msrc)
{
    return (MFIB_SRC_OK);
}

static mfib_src_res_t
mfib_entry_src_default_cover_update (mfib_entry_t *mfib_entry,
                                     mfib_entry_src_t *msrc)
{
    return (MFIB_SRC_OK);
}

void
mfib_entry_src_register (mfib_source_t source,
                         const mfib_entry_src_vft *mvft)
{
    mfib_entry_src_vfts[source] = *mvft;
}

void
mfib_entry_src_deactivate (mfib_entry_t *mfib_entry,
                           mfib_entry_src_t *msrc)
{
    if (NULL != msrc)
        mfib_entry_src_vfts[msrc->mfes_src].mev_deactivate(mfib_entry, msrc);
}

void
mfib_entry_src_activate (mfib_entry_t *mfib_entry,
                         mfib_entry_src_t *msrc)
{
    if (NULL != msrc)
        mfib_entry_src_vfts[msrc->mfes_src].mev_activate(mfib_entry, msrc);
}

mfib_src_res_t
mfib_entry_src_cover_change (mfib_entry_t *mfib_entry,
                             mfib_entry_src_t *msrc)
{
    return (mfib_entry_src_vfts[msrc->mfes_src].mev_cover_change(mfib_entry, msrc));
}

mfib_src_res_t
mfib_entry_src_cover_update (mfib_entry_t *mfib_entry,
                             mfib_entry_src_t *msrc)
{
    return (mfib_entry_src_vfts[msrc->mfes_src].mev_cover_update(mfib_entry, msrc));
}

void
mfib_entry_src_module_init (void)
{
    mfib_entry_src_vft mvft = {
        .mev_activate = mfib_entry_src_default_activiate,
        .mev_deactivate = mfib_entry_src_default_deactiviate,
        .mev_cover_change = mfib_entry_src_default_cover_change,
        .mev_cover_update = mfib_entry_src_default_cover_update,
    };
    mfib_source_t source;

    FOREACH_MFIB_SOURCE(source)
    {
        mfib_entry_src_register(source, &mvft);
    }

    mfib_entry_src_rr_module_init();
}
{ span_main_t *sm = &span_main; if (state > SPAN_BOTH) return VNET_API_ERROR_UNIMPLEMENTED; if ((src_sw_if_index == ~0) || (dst_sw_if_index == ~0 && state > 0) || (src_sw_if_index == dst_sw_if_index)) return VNET_API_ERROR_INVALID_INTERFACE; vec_validate_aligned (sm->interfaces, src_sw_if_index, CLIB_CACHE_LINE_BYTES); span_interface_t *si = vec_elt_at_index (sm->interfaces, src_sw_if_index); int rx = ! !(state & SPAN_RX); int tx = ! !(state & SPAN_TX); span_mirror_t *rxm = &si->mirror_rxtx[sf][VLIB_RX]; span_mirror_t *txm = &si->mirror_rxtx[sf][VLIB_TX]; u32 last_rx_ports_count = span_dst_set (rxm, dst_sw_if_index, rx); u32 last_tx_ports_count = span_dst_set (txm, dst_sw_if_index, tx); int enable_rx = last_rx_ports_count == 0 && rxm->num_mirror_ports == 1; int disable_rx = last_rx_ports_count > 0 && rxm->num_mirror_ports == 0; int enable_tx = last_tx_ports_count == 0 && txm->num_mirror_ports == 1; int disable_tx = last_tx_ports_count > 0 && txm->num_mirror_ports == 0; switch (sf) { case SPAN_FEAT_DEVICE: if (enable_rx || disable_rx) vnet_feature_enable_disable ("device-input", "span-input", src_sw_if_index, rx, 0, 0); if (enable_tx || disable_tx) vnet_feature_enable_disable ("interface-output", "span-output", src_sw_if_index, tx, 0, 0); break; case SPAN_FEAT_L2: if (enable_rx || disable_rx) l2input_intf_bitmap_enable (src_sw_if_index, L2INPUT_FEAT_SPAN, rx); if (enable_tx || disable_tx) l2output_intf_bitmap_enable (src_sw_if_index, L2OUTPUT_FEAT_SPAN, tx); break; default: return VNET_API_ERROR_UNIMPLEMENTED; } if (dst_sw_if_index != ~0 && dst_sw_if_index > sm->max_sw_if_index) sm->max_sw_if_index = dst_sw_if_index; return 0; } static uword unformat_span_state (unformat_input_t * input, va_list * args) { span_state_t *state = va_arg (*args, span_state_t *); if (unformat (input, "disable")) *state = SPAN_DISABLE; else if (unformat (input, "rx")) *state = SPAN_RX; else if (unformat (input, "tx")) *state = SPAN_TX; else if (unformat (input, "both")) *state = SPAN_BOTH; else return 0; return 1; } static clib_error_t * set_interface_span_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { span_main_t *sm = &span_main; u32 src_sw_if_index = ~0; u32 dst_sw_if_index = ~0; span_feat_t sf = SPAN_FEAT_DEVICE; span_state_t state = SPAN_BOTH; int state_set = 0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "%U", unformat_vnet_sw_interface, sm->vnet_main, &src_sw_if_index)) ; else if (unformat (input, "destination %U", unformat_vnet_sw_interface, sm->vnet_main, &dst_sw_if_index)) ; else if (unformat (input, "%U", unformat_span_state, &state)) { if (state_set) return clib_error_return (0, "Multiple mirror states in input"); state_set = 1; } else if (unformat (input, "l2")) sf = SPAN_FEAT_L2; else return clib_error_return (0, "Invalid input"); } int rv = span_add_delete_entry (vm, src_sw_if_index, dst_sw_if_index, state, sf); if (rv == VNET_API_ERROR_INVALID_INTERFACE) return clib_error_return (0, "Invalid interface"); return 0; } /* *INDENT-OFF* */ VLIB_CLI_COMMAND (set_interface_span_command, static) = { .path = "set interface span", .short_help = "set interface span <if-name> [l2] {disable | destination <if-name> [both|rx|tx]}", .function = set_interface_span_command_fn, }; /* *INDENT-ON* */ static clib_error_t * show_interfaces_span_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { span_main_t *sm = &span_main; span_interface_t *si; vnet_main_t *vnm = &vnet_main; u8 header = 1; static const char *states[] = { [SPAN_DISABLE] = "none", [SPAN_RX] = "rx", [SPAN_TX] = "tx", [SPAN_BOTH] = "both" }; u8 *s = 0; /* *INDENT-OFF* */ vec_foreach (si, sm->interfaces) { span_mirror_t * drxm = &si->mirror_rxtx[SPAN_FEAT_DEVICE][VLIB_RX]; span_mirror_t * dtxm = &si->mirror_rxtx[SPAN_FEAT_DEVICE][VLIB_TX]; span_mirror_t * lrxm = &si->mirror_rxtx[SPAN_FEAT_L2][VLIB_RX]; span_mirror_t * ltxm = &si->mirror_rxtx[SPAN_FEAT_L2][VLIB_TX]; if (drxm->num_mirror_ports || dtxm->num_mirror_ports || lrxm->num_mirror_ports || ltxm->num_mirror_ports) { u32 i; clib_bitmap_t *d = clib_bitmap_dup_or (drxm->mirror_ports, dtxm->mirror_ports); clib_bitmap_t *l = clib_bitmap_dup_or (lrxm->mirror_ports, ltxm->mirror_ports); clib_bitmap_t *b = clib_bitmap_dup_or (d, l); if (header) { vlib_cli_output (vm, "%-20s %-20s %6s %6s", "Source", "Destination", "Device", "L2"); header = 0; } s = format (s, "%U", format_vnet_sw_if_index_name, vnm, si - sm->interfaces); clib_bitmap_foreach (i, b, ( { int device = (clib_bitmap_get (drxm->mirror_ports, i) + clib_bitmap_get (dtxm->mirror_ports, i) * 2); int l2 = (clib_bitmap_get (lrxm->mirror_ports, i) + clib_bitmap_get (ltxm->mirror_ports, i) * 2); vlib_cli_output (vm, "%-20v %-20U (%6s) (%6s)", s, format_vnet_sw_if_index_name, vnm, i, states[device], states[l2]); vec_reset_length (s); })); clib_bitmap_free (b); clib_bitmap_free (l); clib_bitmap_free (d); } } /* *INDENT-ON* */ vec_free (s); return 0; } /* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_interfaces_span_command, static) = { .path = "show interface span", .short_help = "Shows SPAN mirror table", .function = show_interfaces_span_command_fn, }; /* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */