Skip to content

Commit

Permalink
IGMP: proxy device
Browse files Browse the repository at this point in the history
Create 'proxy device' per VRF and add one upstream
and one or many downstream interfaces.

Change-Id: I1cef05fb01e73a5b483c7a2f4debaaeffe2c8155
Signed-off-by: Jakub Grajciar <[email protected]>
  • Loading branch information
Jakub Grajciar authored and Neale Ranns committed Oct 16, 2018
1 parent 02a95ce commit 97748ca
Show file tree
Hide file tree
Showing 17 changed files with 848 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/plugins/igmp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ add_vpp_plugin(igmp
igmp_pkt.c
igmp_ssm_range.c
igmp_format.c
igmp_proxy.c

API_FILES
igmp.api
Expand Down
42 changes: 42 additions & 0 deletions src/plugins/igmp/igmp.api
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,48 @@ autoreply define igmp_enable_disable
u32 sw_if_index;
};

/**
* @brief
* Add/del proxy device on specified VRF.
* Interface must be IGMP enabled in HOST mode.
*
* @param client_index - opaque cookie to identify the sender
* @param context - sender context, to match reply w/ request
* @param add - add (1) del (0)
* @param vrf_id - VRF id
* @param sw_if_index - upstream interface sw index
*/
autoreply define igmp_proxy_device_add_del
{
u32 client_index;
u32 context;

u8 add;
u32 vrf_id;
u32 sw_if_index;
};

/**
* @brief
* Add/del downstream interface to/from proxy device.
* Interface must be IGMP enabled in ROUTER mode.
*
* @param client_index - opaque cookie to identify the sender
* @param context - sender context, to match reply w/ request
* @param add - add (1) del (0)
* @param vrf_id - VRF id
* @param sw_if_index - downstream interface sw index
*/
autoreply define igmp_proxy_device_add_del_interface
{
u32 client_index;
u32 context;

u8 add;
u32 vrf_id;
u32 sw_if_index;
};

/**
* @brief dump (S,G)s from interface
* @param client_index - opaque cookie to identify the sender
Expand Down
13 changes: 13 additions & 0 deletions src/plugins/igmp/igmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ igmp_enable_disable (u32 sw_if_index, u8 enable, igmp_mode_t mode)
hash_create_mem (0, sizeof (igmp_key_t), sizeof (uword));
config->robustness_var = IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
config->mode = mode;
config->proxy_device_id = ~0;

for (ii = 0; ii < IGMP_CONFIG_N_TIMERS; ii++)
config->timers[ii] = IGMP_TIMER_ID_INVALID;
Expand Down Expand Up @@ -445,6 +446,18 @@ igmp_enable_disable (u32 sw_if_index, u8 enable, igmp_mode_t mode)
mfib_table_entry_path_remove (mfib_index,
&mpfx_report,
MFIB_SOURCE_IGMP, &via_itf_path);

/*
* remove interface from proxy device
* if this device is upstream, delete proxy device
*/
if (config->mode == IGMP_MODE_ROUTER)
igmp_proxy_device_add_del_interface (config->proxy_device_id,
config->sw_if_index, 0);
else if (config->mode == IGMP_MODE_HOST)
igmp_proxy_device_add_del (config->proxy_device_id,
config->sw_if_index, 0);

igmp_clear_config (config);
im->igmp_config_by_sw_if_index[config->sw_if_index] = ~0;
hash_free (config->igmp_group_by_key);
Expand Down
11 changes: 11 additions & 0 deletions src/plugins/igmp/igmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <igmp/igmp_timer.h>
#include <igmp/igmp_group.h>
#include <igmp/igmp_config.h>
#include <igmp/igmp_proxy.h>

/**
* RFC 3376 Section 8.1
Expand Down Expand Up @@ -101,6 +102,16 @@ typedef struct igmp_main_t_
* pool of sources
*/
igmp_src_t *srcs;

/**
* per-vrf DB of proxy devices
*/
u32 *igmp_proxy_device_by_vrf_id;

/**
* pool of proxy devices
*/
igmp_proxy_device_t *proxy_devices;
} igmp_main_t;

extern igmp_main_t igmp_main;
Expand Down
57 changes: 48 additions & 9 deletions src/plugins/igmp/igmp_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,17 @@

#define IGMP_MSG_ID(_id) (_id + igmp_main.msg_id_base)

#define foreach_igmp_plugin_api_msg \
_(IGMP_LISTEN, igmp_listen) \
_(IGMP_ENABLE_DISABLE, igmp_enable_disable) \
_(IGMP_DUMP, igmp_dump) \
_(IGMP_CLEAR_INTERFACE, igmp_clear_interface) \
_(IGMP_CLEAR_INTERFACE, igmp_clear_interface) \
_(IGMP_GROUP_PREFIX_SET, igmp_group_prefix_set) \
_(IGMP_GROUP_PREFIX_DUMP, igmp_group_prefix_dump) \
_(WANT_IGMP_EVENTS, want_igmp_events) \
#define foreach_igmp_plugin_api_msg \
_(IGMP_LISTEN, igmp_listen) \
_(IGMP_ENABLE_DISABLE, igmp_enable_disable) \
_(IGMP_PROXY_DEVICE_ADD_DEL, igmp_proxy_device_add_del) \
_(IGMP_PROXY_DEVICE_ADD_DEL_INTERFACE, igmp_proxy_device_add_del_interface) \
_(IGMP_DUMP, igmp_dump) \
_(IGMP_CLEAR_INTERFACE, igmp_clear_interface) \
_(IGMP_CLEAR_INTERFACE, igmp_clear_interface) \
_(IGMP_GROUP_PREFIX_SET, igmp_group_prefix_set) \
_(IGMP_GROUP_PREFIX_DUMP, igmp_group_prefix_dump) \
_(WANT_IGMP_EVENTS, want_igmp_events) \

static void
vl_api_igmp_listen_t_handler (vl_api_igmp_listen_t * mp)
Expand Down Expand Up @@ -120,6 +122,43 @@ vl_api_igmp_enable_disable_t_handler (vl_api_igmp_enable_disable_t * mp)
REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_ENABLE_DISABLE_REPLY));
}

static void
vl_api_igmp_proxy_device_add_del_t_handler (vl_api_igmp_proxy_device_add_del_t
* mp)
{
vl_api_igmp_proxy_device_add_del_reply_t *rmp;
int rv = 0;

VALIDATE_SW_IF_INDEX (mp);

rv =
igmp_proxy_device_add_del (ntohl (mp->vrf_id), ntohl (mp->sw_if_index),
mp->add);

BAD_SW_IF_INDEX_LABEL;

REPLY_MACRO (IGMP_MSG_ID (VL_API_IGMP_PROXY_DEVICE_ADD_DEL_REPLY));
}

static void
vl_api_igmp_proxy_device_add_del_interface_t_handler
(vl_api_igmp_proxy_device_add_del_interface_t * mp)
{
vl_api_igmp_proxy_device_add_del_interface_reply_t *rmp;
int rv = 0;

VALIDATE_SW_IF_INDEX (mp);

rv =
igmp_proxy_device_add_del_interface (ntohl (mp->vrf_id),
ntohl (mp->sw_if_index), mp->add);

BAD_SW_IF_INDEX_LABEL;

REPLY_MACRO (IGMP_MSG_ID
(VL_API_IGMP_PROXY_DEVICE_ADD_DEL_INTERFACE_REPLY));
}

static void
send_igmp_details (unix_shared_memory_queue_t * q, igmp_main_t * im,
igmp_config_t * config, igmp_group_t * group,
Expand Down
132 changes: 130 additions & 2 deletions src/plugins/igmp/igmp_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,134 @@ VLIB_CLI_COMMAND (igmp_enable_command, static) = {
};
/* *INDENT-ON* */

static clib_error_t *
igmp_proxy_device_add_del_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
unformat_input_t _line_input, *line_input = &_line_input;
vnet_main_t *vnm = vnet_get_main ();
clib_error_t *error = NULL;
u32 sw_if_index = ~0;
u32 vrf_id = ~0;
u8 add = 1;
int rv;

if (!unformat_user (input, unformat_line_input, line_input))
return error;

while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (line_input, "add"))
add = 1;
else if (unformat (line_input, "del"))
add = 0;
else if (unformat (line_input, "vrf-id %u", &vrf_id))
;
else if (unformat (line_input, "%U",
unformat_vnet_sw_interface, vnm, &sw_if_index));
else
{
error =
clib_error_return (0, "unknown input '%U'", format_unformat_error,
line_input);
goto done;
}
}

if (~0 == sw_if_index)
{
error = clib_error_return (0, "interface must be specified");
goto done;
}

if (~0 == vrf_id)
{
error = clib_error_return (0, "VRF must be specified");
goto done;
}

rv = igmp_proxy_device_add_del (vrf_id, sw_if_index, add);

if (0 != rv)
error = clib_error_return (0, "result: %d", rv);

done:
unformat_free (line_input);
return error;
}
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (igmp_proxy_device_add_del_command, static) = {
.path = "igmp proxy-dev",
.short_help = "igmp proxy-dev <add|del> vrf-id <table-id> <interface>",
.function = igmp_proxy_device_add_del_command_fn,
};
/* *INDENT-ON* */

static clib_error_t *
igmp_proxy_device_add_del_interface_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
unformat_input_t _line_input, *line_input = &_line_input;
vnet_main_t *vnm = vnet_get_main ();
clib_error_t *error = NULL;
u32 sw_if_index = ~0;
u32 vrf_id = ~0;
u8 add = 1;
int rv;

if (!unformat_user (input, unformat_line_input, line_input))
return error;

while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (line_input, "add"))
add = 1;
else if (unformat (line_input, "del"))
add = 0;
else if (unformat (line_input, "vrf-id %u", &vrf_id))
;
else if (unformat (line_input, "%U",
unformat_vnet_sw_interface, vnm, &sw_if_index));
else
{
error =
clib_error_return (0, "unknown input '%U'", format_unformat_error,
line_input);
goto done;
}
}

if (~0 == sw_if_index)
{
error = clib_error_return (0, "interface must be specified");
goto done;
}

if (~0 == vrf_id)
{
error = clib_error_return (0, "VRF must be specified");
goto done;
}

rv = igmp_proxy_device_add_del_interface (vrf_id, sw_if_index, add);

if (0 != rv)
error = clib_error_return (0, "result: %d", rv);

done:
unformat_free (line_input);
return error;
}
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (igmp_proxy_device_add_del_interface_command, static) = {
.path = "igmp proxy-dev itf",
.short_help = "igmp proxy-dev itf <add|del> vrf-id <table-id> <interface>",
.function = igmp_proxy_device_add_del_interface_command_fn,
};
/* *INDENT-ON* */

static clib_error_t *
igmp_show_command_fn (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_command_t * cmd)
Expand All @@ -233,9 +361,9 @@ igmp_show_command_fn (vlib_main_t * vm, unformat_input_t * input,
/* *INDENT-OFF* */
pool_foreach (config, im->configs,
({
vlib_cli_output (vm, "interface: %U mode:%U",
vlib_cli_output (vm, "interface: %U mode: %U %U",
format_vnet_sw_if_index_name, vnm, config->sw_if_index,
format_igmp_mode, config->mode);
format_igmp_mode, config->mode, format_igmp_proxy_device_id, config->proxy_device_id);

FOR_EACH_GROUP (group, config,
({
Expand Down
7 changes: 6 additions & 1 deletion src/plugins/igmp/igmp_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ typedef struct igmp_config_t_
adj_index_t adj_index;

/**
* @param moe - host or router
* @param mode - host or router
*/
igmp_mode_t mode;

Expand All @@ -71,6 +71,11 @@ typedef struct igmp_config_t_
* A vector of scheduled query-response timers
*/
igmp_timer_id_t timers[IGMP_CONFIG_N_TIMERS];

/**
* ID of a proxy device this configuration is on
*/
u32 proxy_device_id;
} igmp_config_t;

#define FOR_EACH_GROUP(_group, _config, _body) \
Expand Down
10 changes: 10 additions & 0 deletions src/plugins/igmp/igmp_format.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,16 @@ format_igmp_key (u8 * s, va_list * args)
return (s);
}

u8 *
format_igmp_proxy_device_id (u8 * s, va_list * args)
{
u32 id = va_arg (*args, u32);

s = (id == ~0) ? s : format (s, "proxy device: %u", id);

return (s);
}

/*
* fd.io coding-style-patch-verification: ON
*
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/igmp/igmp_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ extern u8 *format_igmp_src_addr_list (u8 * s, va_list * args);

extern u8 *format_igmp_key (u8 * s, va_list * args);

extern u8 *format_igmp_proxy_device_id (u8 * s, va_list * args);

#endif /* IGMP_FORMAT_H */

/*
Expand Down
Loading

0 comments on commit 97748ca

Please sign in to comment.