From 7866c4595b65f54f491ffc4e92b1f8cf94d6f142 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Thu, 18 Jan 2018 13:35:11 +0100 Subject: tapv2: add option to set host-side default gw Change-Id: I76fd655ecd9445299b94b3b5af10e7b1588584e4 Signed-off-by: Damjan Marion --- src/vat/api_format.c | 15 +++++++++++++- src/vnet/devices/netlink.c | 42 ++++++++++++++++++++++++++++++++++++++++ src/vnet/devices/netlink.h | 2 ++ src/vnet/devices/tap/cli.c | 9 ++++++++- src/vnet/devices/tap/tap.c | 20 +++++++++++++++++++ src/vnet/devices/tap/tap.h | 4 ++++ src/vnet/devices/tap/tapv2.api | 10 +++++++++- src/vnet/devices/tap/tapv2_api.c | 12 ++++++++++++ src/vpp/api/custom_dump.c | 4 ++++ 9 files changed, 115 insertions(+), 3 deletions(-) diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 3654cd663bd..4f20ea82361 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -7772,8 +7772,12 @@ api_tap_create_v2 (vat_main_t * vam) u8 host_mac_addr_set = 0; u8 *host_bridge = 0; ip4_address_t host_ip4_addr; + ip4_address_t host_ip4_gw; + u8 host_ip4_gw_set = 0; u32 host_ip4_prefix_len = 0; ip6_address_t host_ip6_addr; + ip6_address_t host_ip6_gw; + u8 host_ip6_gw_set = 0; u32 host_ip6_prefix_len = 0; int ret; int rx_ring_sz = 0, tx_ring_sz = 0; @@ -7804,6 +7808,12 @@ api_tap_create_v2 (vat_main_t * vam) else if (unformat (i, "host-ip6-addr %U/%d", unformat_ip6_address, &host_ip6_addr, &host_ip6_prefix_len)) ; + else if (unformat (i, "host-ip4-gw %U", unformat_ip4_address, + &host_ip4_gw)) + host_ip4_gw_set = 1; + else if (unformat (i, "host-ip6-gw %U", unformat_ip6_address, + &host_ip6_gw)) + host_ip6_gw_set = 1; else if (unformat (i, "rx-ring-size %d", &rx_ring_sz)) ; else if (unformat (i, "tx-ring-size %d", &tx_ring_sz)) @@ -7885,7 +7895,10 @@ api_tap_create_v2 (vat_main_t * vam) clib_memcpy (mp->host_ip4_addr, &host_ip4_addr, 4); if (host_ip4_prefix_len) clib_memcpy (mp->host_ip6_addr, &host_ip6_addr, 16); - + if (host_ip4_gw_set) + clib_memcpy (mp->host_ip4_gw, &host_ip4_gw, 4); + if (host_ip6_gw_set) + clib_memcpy (mp->host_ip6_gw, &host_ip6_gw, 16); vec_free (host_ns); vec_free (host_if_name); diff --git a/src/vnet/devices/netlink.c b/src/vnet/devices/netlink.c index 5994366007c..8346b1c77ea 100644 --- a/src/vnet/devices/netlink.c +++ b/src/vnet/devices/netlink.c @@ -245,6 +245,48 @@ vnet_netlink_add_ip6_addr (int ifindex, void *addr, int pfx_len) return vnet_netlink_msg_send (&m); } +clib_error_t * +vnet_netlink_add_ip4_route (void *dst, u8 dst_len, void *gw) +{ + vnet_netlink_msg_t m; + struct rtmsg rtm = { 0 }; + u8 dflt[4] = { 0 }; + + rtm.rtm_family = AF_INET; + rtm.rtm_table = RT_TABLE_MAIN; + rtm.rtm_type = RTN_UNICAST; + rtm.rtm_dst_len = dst_len; + + vnet_netlink_msg_init (&m, RTM_NEWROUTE, + NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL, + &rtm, sizeof (struct rtmsg)); + + vnet_netlink_msg_add_rtattr (&m, RTA_GATEWAY, gw, 4); + vnet_netlink_msg_add_rtattr (&m, RTA_DST, dst ? dst : dflt, 4); + return vnet_netlink_msg_send (&m); +} + +clib_error_t * +vnet_netlink_add_ip6_route (void *dst, u8 dst_len, void *gw) +{ + vnet_netlink_msg_t m; + struct rtmsg rtm = { 0 }; + u8 dflt[16] = { 0 }; + + rtm.rtm_family = AF_INET6; + rtm.rtm_table = RT_TABLE_MAIN; + rtm.rtm_type = RTN_UNICAST; + rtm.rtm_dst_len = dst_len; + + vnet_netlink_msg_init (&m, RTM_NEWROUTE, + NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL, + &rtm, sizeof (struct rtmsg)); + + vnet_netlink_msg_add_rtattr (&m, RTA_GATEWAY, gw, 16); + vnet_netlink_msg_add_rtattr (&m, RTA_DST, dst ? dst : dflt, 16); + return vnet_netlink_msg_send (&m); +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vnet/devices/netlink.h b/src/vnet/devices/netlink.h index e8501961a04..0d3e0d23ac6 100644 --- a/src/vnet/devices/netlink.h +++ b/src/vnet/devices/netlink.h @@ -26,6 +26,8 @@ clib_error_t *vnet_netlink_add_ip4_addr (int ifindex, void *addr, int pfx_len); clib_error_t *vnet_netlink_add_ip6_addr (int ifindex, void *addr, int pfx_len); +clib_error_t *vnet_netlink_add_ip4_route (void *dst, u8 dst_len, void *gw); +clib_error_t *vnet_netlink_add_ip6_route (void *dst, u8 dst_len, void *gw); #endif /* included_vnet_device_netlink_h */ diff --git a/src/vnet/devices/tap/cli.c b/src/vnet/devices/tap/cli.c index 7dd525b169d..c17599afdad 100644 --- a/src/vnet/devices/tap/cli.c +++ b/src/vnet/devices/tap/cli.c @@ -61,10 +61,16 @@ tap_create_command_fn (vlib_main_t * vm, unformat_input_t * input, unformat_ip4_address, &args.host_ip4_addr, &args.host_ip4_prefix_len)) ip_addr_set = 1; + else if (unformat (line_input, "host-ip4-gw %U", + unformat_ip4_address, &args.host_ip4_gw)) + args.host_ip4_gw_set = 1; else if (unformat (line_input, "host-ip6-addr %U/%d", unformat_ip6_address, &args.host_ip6_addr, &args.host_ip6_prefix_len)) ip_addr_set = 1; + else if (unformat (line_input, "host-ip6-gw %U", + unformat_ip6_address, &args.host_ip6_gw)) + args.host_ip6_gw_set = 1; else if (unformat (line_input, "rx-ring-size %d", &args.rx_ring_sz)) ; else if (unformat (line_input, "tx-ring-size %d", &args.tx_ring_sz)) @@ -102,7 +108,8 @@ VLIB_CLI_COMMAND (tap_create_command, static) = { .short_help = "create tap {id } [hw-addr ] " "[rx-ring-size ] [tx-ring-size ] [host-ns ] " "[host-bridge ] [host-ip4-addr ] " - "[host-ip6-addr ]", + "[host-ip6-addr ] [host-ip4-gw ] " + "[host-ip6-gw ] [host-if-name ]", .function = tap_create_command_fn, }; /* *INDENT-ON* */ diff --git a/src/vnet/devices/tap/tap.c b/src/vnet/devices/tap/tap.c index a7d10fe5473..e6a7ba518a6 100644 --- a/src/vnet/devices/tap/tap.c +++ b/src/vnet/devices/tap/tap.c @@ -292,6 +292,26 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) goto error; } + if (args->host_ip4_gw_set) + { + args->error = vnet_netlink_add_ip4_route (0, 0, &args->host_ip4_gw); + if (args->error) + { + args->rv = VNET_API_ERROR_NETLINK_ERROR; + goto error; + } + } + + if (args->host_ip6_gw_set) + { + args->error = vnet_netlink_add_ip6_route (0, 0, &args->host_ip6_gw); + if (args->error) + { + args->rv = VNET_API_ERROR_NETLINK_ERROR; + goto error; + } + } + /* switch back to old net namespace */ if (args->host_namespace) { diff --git a/src/vnet/devices/tap/tap.h b/src/vnet/devices/tap/tap.h index 35f7a018237..98af0d8f3ab 100644 --- a/src/vnet/devices/tap/tap.h +++ b/src/vnet/devices/tap/tap.h @@ -35,8 +35,12 @@ typedef struct u8 *host_bridge; ip4_address_t host_ip4_addr; u8 host_ip4_prefix_len; + ip4_address_t host_ip4_gw; + u8 host_ip4_gw_set; ip6_address_t host_ip6_addr; u8 host_ip6_prefix_len; + ip6_address_t host_ip6_gw; + u8 host_ip6_gw_set; /* return */ u32 sw_if_index; int rv; diff --git a/src/vnet/devices/tap/tapv2.api b/src/vnet/devices/tap/tapv2.api index 1f0051ec86f..0d86edff735 100644 --- a/src/vnet/devices/tap/tapv2.api +++ b/src/vnet/devices/tap/tapv2.api @@ -19,7 +19,7 @@ the Linux kernel TAP device driver */ -vl_api_version 1.0.0 +vl_api_version 1.1.0 /** \brief Initialize a new tap interface with the given paramters @param client_index - opaque cookie to identify the sender @@ -43,6 +43,10 @@ vl_api_version 1.0.0 @param host_ip6_addr_set - host IPv6 ip address should be set @param host_ip6_addr - host IPv6 ip address @param host_ip6_prefix_len - host IPv6 ip address prefix length + @param host_ip4_gw_set - host IPv4 default gateway should be set + @param host_ip4_gw - host IPv4 default gateway + @param host_ip6_gw_set - host IPv6 default gateway should be set + @param host_ip6_gw - host IPv6 default gateway */ define tap_create_v2 { @@ -67,6 +71,10 @@ define tap_create_v2 u8 host_ip6_addr_set; u8 host_ip6_addr[16]; u8 host_ip6_prefix_len; + u8 host_ip4_gw_set; + u8 host_ip4_gw[4]; + u8 host_ip6_gw_set; + u8 host_ip6_gw[16]; }; /** \brief Reply for tap create reply diff --git a/src/vnet/devices/tap/tapv2_api.c b/src/vnet/devices/tap/tapv2_api.c index 9f46884ca8c..34472c0ab28 100644 --- a/src/vnet/devices/tap/tapv2_api.c +++ b/src/vnet/devices/tap/tapv2_api.c @@ -96,6 +96,18 @@ vl_api_tap_create_v2_t_handler (vl_api_tap_create_v2_t * mp) ap->host_ip6_prefix_len = mp->host_ip6_prefix_len; } + if (mp->host_ip4_gw_set) + { + clib_memcpy (&ap->host_ip4_gw, mp->host_ip4_gw, 4); + ap->host_ip4_gw_set = 1; + } + + if (mp->host_ip6_gw_set) + { + clib_memcpy (&ap->host_ip6_gw, mp->host_ip6_gw, 16); + ap->host_ip6_gw_set = 1; + } + tap_create_if (vm, ap); reg = vl_api_client_index_to_registration (mp->client_index); diff --git a/src/vpp/api/custom_dump.c b/src/vpp/api/custom_dump.c index 2af3b47d388..62f3c5f4af5 100644 --- a/src/vpp/api/custom_dump.c +++ b/src/vpp/api/custom_dump.c @@ -576,6 +576,10 @@ static void *vl_api_tap_create_v2_t_print if (mp->host_ip6_addr_set) s = format (s, "host-ip6-addr %U/%d ", format_ip6_address, mp->host_ip6_addr, mp->host_ip6_prefix_len); + if (mp->host_ip4_gw_set) + s = format (s, "host-ip4-gw %U ", format_ip4_address, mp->host_ip4_addr); + if (mp->host_ip6_gw_set) + s = format (s, "host-ip6-gw %U ", format_ip6_address, mp->host_ip6_addr); if (mp->tx_ring_sz) s = format (s, "tx-ring-size %d ", mp->tx_ring_sz); if (mp->rx_ring_sz) -- cgit 1.2.3-korg