aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOle Troan <ot@cisco.com>2020-06-17 22:57:13 +0200
committerAndrew Yourtchenko <ayourtch@gmail.com>2020-07-24 09:28:04 +0000
commit7fc88cf3a1236ebf9f21a2054eee7d586e031e5f (patch)
treea3a34e333a1dd0d1952fb3254b163aabfe6dcc13
parent5a849e3b359dcf8f730429e1ccb7421f1c4217b6 (diff)
geneve: support geneve interface acting as a bvi
create geneve tunnel local 10.10.10.10 remote 10.10.10.9 vni 48 decap-next node ethernet-input l3-mode set interface ip address geneve_tunnel0 11.11.11.12/24 Type: feature Change-Id: I579ce879553d72a2e8048e33d0c0122674996b81 Signed-off-by: Ole Troan <ot@cisco.com>
-rw-r--r--src/vnet/geneve/geneve.api24
-rw-r--r--src/vnet/geneve/geneve.c67
-rw-r--r--src/vnet/geneve/geneve.h6
-rw-r--r--src/vnet/geneve/geneve_api.c53
-rw-r--r--test/test_geneve.py73
5 files changed, 189 insertions, 34 deletions
diff --git a/src/vnet/geneve/geneve.api b/src/vnet/geneve/geneve.api
index 5fad670b9db..4502d890797 100644
--- a/src/vnet/geneve/geneve.api
+++ b/src/vnet/geneve/geneve.api
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-option version = "2.0.0";
+option version = "2.1.0";
import "vnet/interface_types.api";
import "vnet/ethernet/ethernet_types.api";
@@ -21,6 +21,7 @@ import "vnet/ip/ip_types.api";
define geneve_add_del_tunnel
{
+ option deprecated="20.06";
u32 client_index;
u32 context;
bool is_add;
@@ -39,6 +40,27 @@ define geneve_add_del_tunnel_reply
vl_api_interface_index_t sw_if_index;
};
+define geneve_add_del_tunnel2
+{
+ u32 client_index;
+ u32 context;
+ bool is_add;
+ vl_api_address_t local_address;
+ vl_api_address_t remote_address;
+ vl_api_interface_index_t mcast_sw_if_index;
+ u32 encap_vrf_id;
+ u32 decap_next_index;
+ u32 vni;
+ bool l3_mode;
+};
+
+define geneve_add_del_tunnel2_reply
+{
+ u32 context;
+ i32 retval;
+ vl_api_interface_index_t sw_if_index;
+};
+
define geneve_tunnel_dump
{
u32 client_index;
diff --git a/src/vnet/geneve/geneve.c b/src/vnet/geneve/geneve.c
index 1e04c662431..e16616b69ea 100644
--- a/src/vnet/geneve/geneve.c
+++ b/src/vnet/geneve/geneve.c
@@ -81,6 +81,7 @@ format_geneve_tunnel (u8 * s, va_list * args)
s = format (s, "encap-dpo-idx %d ", t->next_dpo.dpoi_index);
s = format (s, "decap-next-%U ", format_decap_next, t->decap_next_index);
+ s = format (s, "l3-mode %u ", t->l3_mode);
if (PREDICT_FALSE (ip46_address_is_multicast (&t->remote)))
s = format (s, "mcast-sw-if-idx %d ", t->mcast_sw_if_index);
@@ -105,12 +106,21 @@ geneve_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
return /* no error */ 0;
}
+static clib_error_t *
+geneve_mac_change (vnet_hw_interface_t * hi,
+ const u8 * old_address, const u8 * mac_address)
+{
+ l2input_interface_mac_change (hi->sw_if_index, old_address, mac_address);
+ return (NULL);
+}
+
/* *INDENT-OFF* */
VNET_DEVICE_CLASS (geneve_device_class, static) = {
.name = "GENEVE",
.format_device_name = format_geneve_name,
.format_tx_trace = format_geneve_encap_trace,
.admin_up_down_function = geneve_interface_admin_up_down,
+ .mac_addr_change_function = geneve_mac_change,
};
/* *INDENT-ON* */
@@ -206,8 +216,9 @@ _(vni) \
_(mcast_sw_if_index) \
_(encap_fib_index) \
_(decap_next_index) \
-_(local) \
-_(remote)
+_(local) \
+_(remote) \
+_(l3_mode)
static int
geneve_rewrite (geneve_tunnel_t * t, bool is_ip6)
@@ -400,39 +411,30 @@ int vnet_geneve_add_del_tunnel
hash_set (vxm->geneve4_tunnel_by_key, key4.as_u64, t - vxm->tunnels);
vnet_hw_interface_t *hi;
- if (vec_len (vxm->free_geneve_tunnel_hw_if_indices) > 0)
+ if (a->l3_mode)
{
- vnet_interface_main_t *im = &vnm->interface_main;
- hw_if_index = vxm->free_geneve_tunnel_hw_if_indices
- [vec_len (vxm->free_geneve_tunnel_hw_if_indices) - 1];
- _vec_len (vxm->free_geneve_tunnel_hw_if_indices) -= 1;
-
- hi = vnet_get_hw_interface (vnm, hw_if_index);
- hi->dev_instance = t - vxm->tunnels;
- hi->hw_instance = hi->dev_instance;
-
- /* clear old stats of freed tunnel before reuse */
- sw_if_index = hi->sw_if_index;
- vnet_interface_counter_lock (im);
- vlib_zero_combined_counter
- (&im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX],
- sw_if_index);
- vlib_zero_combined_counter (&im->combined_sw_if_counters
- [VNET_INTERFACE_COUNTER_RX],
- sw_if_index);
- vlib_zero_simple_counter (&im->sw_if_counters
- [VNET_INTERFACE_COUNTER_DROP],
- sw_if_index);
- vnet_interface_counter_unlock (im);
+ u32 t_idx = t - vxm->tunnels;
+ u8 address[6] =
+ { 0xd0, 0x0b, 0xee, 0xd0, (u8) (t_idx >> 8), (u8) t_idx };
+ clib_error_t *error =
+ ethernet_register_interface (vnm, geneve_device_class.index,
+ t_idx,
+ address, &hw_if_index, 0);
+ if (error)
+ {
+ clib_error_report (error);
+ return VNET_API_ERROR_INVALID_REGISTRATION;
+ }
}
else
{
hw_if_index = vnet_register_interface
(vnm, geneve_device_class.index, t - vxm->tunnels,
geneve_hw_class.index, t - vxm->tunnels);
- hi = vnet_get_hw_interface (vnm, hw_if_index);
}
+ hi = vnet_get_hw_interface (vnm, hw_if_index);
+
/* Set geneve tunnel output node */
u32 encap_index = !is_ip6 ?
geneve4_encap_node.index : geneve6_encap_node.index;
@@ -564,7 +566,11 @@ int vnet_geneve_add_del_tunnel
/* make sure tunnel is removed from l2 bd or xconnect */
set_int_l2_mode (vxm->vlib_main, vnm, MODE_L3, t->sw_if_index, 0,
L2_BD_PORT_TYPE_NORMAL, 0, 0);
- vec_add1 (vxm->free_geneve_tunnel_hw_if_indices, t->hw_if_index);
+
+ if (t->l3_mode)
+ ethernet_delete_interface (vnm, t->hw_if_index);
+ else
+ vnet_delete_hw_interface (vnm, t->hw_if_index);
vxm->tunnel_index_by_sw_if_index[t->sw_if_index] = ~0;
@@ -651,6 +657,7 @@ geneve_add_del_tunnel_command_fn (vlib_main_t * vm,
u8 grp_set = 0;
u8 ipv4_set = 0;
u8 ipv6_set = 0;
+ u8 l3_mode = 0;
u32 encap_fib_index = 0;
u32 mcast_sw_if_index = ~0;
u32 decap_next_index = GENEVE_INPUT_NEXT_L2_INPUT;
@@ -736,6 +743,10 @@ geneve_add_del_tunnel_command_fn (vlib_main_t * vm,
goto done;
}
}
+ else if (unformat (line_input, "l3-mode"))
+ {
+ l3_mode = 1;
+ }
else
{
error = clib_error_return (0, "parse error: '%U'",
@@ -864,7 +875,7 @@ VLIB_CLI_COMMAND (create_geneve_tunnel_command, static) = {
.short_help =
"create geneve tunnel local <local-vtep-addr>"
" {remote <remote-vtep-addr>|group <mcast-vtep-addr> <intf-name>} vni <nn>"
- " [encap-vrf-id <nn>] [decap-next [l2|node <name>]] [del]",
+ " [encap-vrf-id <nn>] [decap-next [l2|node <name>]] [l3-mode] [del]",
.function = geneve_add_del_tunnel_command_fn,
};
/* *INDENT-ON* */
diff --git a/src/vnet/geneve/geneve.h b/src/vnet/geneve/geneve.h
index 491ae23242f..0b962e79883 100644
--- a/src/vnet/geneve/geneve.h
+++ b/src/vnet/geneve/geneve.h
@@ -135,6 +135,8 @@ typedef struct
* The tunnels sibling index on the FIB entry's dependency list.
*/
u32 sibling_index;
+
+ u8 l3_mode;
} geneve_tunnel_t;
#define foreach_geneve_input_next \
@@ -173,9 +175,6 @@ typedef struct
/* mcast shared info */
uword *mcast_shared; /* keyed on mcast ip46 addr */
- /* Free vlib hw_if_indices */
- u32 *free_geneve_tunnel_hw_if_indices;
-
/* Mapping from sw_if_index to tunnel index */
u32 *tunnel_index_by_sw_if_index;
@@ -205,6 +204,7 @@ typedef struct
u32 encap_fib_index;
u32 decap_next_index;
u32 vni;
+ u8 l3_mode;
} vnet_geneve_add_del_tunnel_args_t;
int vnet_geneve_add_del_tunnel
diff --git a/src/vnet/geneve/geneve_api.c b/src/vnet/geneve/geneve_api.c
index 996a7a029e0..10dafd2d63b 100644
--- a/src/vnet/geneve/geneve_api.c
+++ b/src/vnet/geneve/geneve_api.c
@@ -45,6 +45,7 @@
#define foreach_vpe_api_msg \
_(SW_INTERFACE_SET_GENEVE_BYPASS, sw_interface_set_geneve_bypass) \
_(GENEVE_ADD_DEL_TUNNEL, geneve_add_del_tunnel) \
+_(GENEVE_ADD_DEL_TUNNEL2, geneve_add_del_tunnel2) \
_(GENEVE_TUNNEL_DUMP, geneve_tunnel_dump)
static void
@@ -114,6 +115,58 @@ out:
/* *INDENT-ON* */
}
+static void vl_api_geneve_add_del_tunnel2_t_handler
+ (vl_api_geneve_add_del_tunnel2_t * mp)
+{
+ vl_api_geneve_add_del_tunnel2_reply_t *rmp;
+ int rv = 0;
+ ip4_main_t *im = &ip4_main;
+
+ uword *p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
+ if (!p)
+ {
+ rv = VNET_API_ERROR_NO_SUCH_FIB;
+ goto out;
+ }
+
+ vnet_geneve_add_del_tunnel_args_t a = {
+ .is_add = mp->is_add,
+ .is_ip6 = mp->remote_address.af,
+ .mcast_sw_if_index = ntohl (mp->mcast_sw_if_index),
+ .encap_fib_index = p[0],
+ .decap_next_index = ntohl (mp->decap_next_index),
+ .vni = ntohl (mp->vni),
+ .l3_mode = mp->l3_mode,
+ };
+
+ ip_address_decode (&mp->remote_address, &a.remote);
+ ip_address_decode (&mp->local_address, &a.local);
+
+ /* Check src & dst are different */
+ if (ip46_address_cmp (&a.remote, &a.local) == 0)
+ {
+ rv = VNET_API_ERROR_SAME_SRC_DST;
+ goto out;
+ }
+ if (ip46_address_is_multicast (&a.remote) &&
+ !vnet_sw_if_index_is_api_valid (a.mcast_sw_if_index))
+ {
+ rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
+ goto out;
+ }
+
+ u32 sw_if_index = ~0;
+ rv = vnet_geneve_add_del_tunnel (&a, &sw_if_index);
+
+out:
+ /* *INDENT-OFF* */
+ REPLY_MACRO2(VL_API_GENEVE_ADD_DEL_TUNNEL2_REPLY,
+ ({
+ rmp->sw_if_index = ntohl (sw_if_index);
+ }));
+ /* *INDENT-ON* */
+}
+
static void send_geneve_tunnel_details
(geneve_tunnel_t * t, vl_api_registration_t * reg, u32 context)
{
diff --git a/test/test_geneve.py b/test/test_geneve.py
index 16cb6c26642..11d69358b96 100644
--- a/test/test_geneve.py
+++ b/test/test_geneve.py
@@ -6,8 +6,8 @@ import unittest
from framework import VppTestCase, VppTestRunner
from template_bd import BridgeDomain
-from scapy.layers.l2 import Ether
-from scapy.layers.inet import IP, UDP
+from scapy.layers.l2 import Ether, ARP
+from scapy.layers.inet import IP, UDP, ICMP
from scapy.contrib.geneve import GENEVE
import util
@@ -234,5 +234,74 @@ class TestGeneve(BridgeDomain, VppTestCase):
self.logger.info(self.vapi.cli("show geneve tunnel"))
+class TestGeneveL3(VppTestCase):
+ """ GENEVE L3 Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestGeneveL3, cls).setUpClass()
+ try:
+ cls.create_pg_interfaces(range(2))
+ cls.interfaces = list(cls.pg_interfaces)
+
+ for i in cls.interfaces:
+ i.admin_up()
+ i.config_ip4()
+ i.resolve_arp()
+ except Exception:
+ super(TestGeneveL3, cls).tearDownClass()
+ raise
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestGeneveL3, cls).tearDownClass()
+
+ def tearDown(self):
+ super(TestGeneveL3, self).tearDown()
+
+ def show_commands_at_teardown(self):
+ self.logger.info(self.vapi.cli("show geneve tunnel"))
+ self.logger.info(self.vapi.cli("show ip neighbor"))
+
+ def test_l3_packet(self):
+ vni = 1234
+ r = self.vapi.add_node_next(node_name="geneve4-input",
+ next_name="ethernet-input")
+ r = self.vapi.geneve_add_del_tunnel2(
+ is_add=1,
+ local_address=self.pg0.local_ip4,
+ remote_address=self.pg0.remote_ip4,
+ vni=vni,
+ l3_mode=1,
+ decap_next_index=r.node_index)
+
+ self.vapi.sw_interface_add_del_address(
+ sw_if_index=r.sw_if_index, prefix="10.0.0.1/24")
+
+ pkt = (Ether(src=self.pg0.remote_mac, dst="d0:0b:ee:d0:00:00") /
+ IP(src='10.0.0.2', dst='10.0.0.1') /
+ ICMP())
+
+ encap = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
+ UDP(sport=6081, dport=6081, chksum=0) /
+ GENEVE(vni=vni))
+
+ arp = (Ether(src=self.pg0.remote_mac, dst="d0:0b:ee:d0:00:00") /
+ ARP(op="is-at", hwsrc=self.pg0.remote_mac,
+ hwdst="d0:0b:ee:d0:00:00", psrc="10.0.0.2",
+ pdst="10.0.0.1"))
+
+ rx = self.send_and_expect(self.pg0, encap/pkt*1, self.pg0)
+ rx = self.send_and_assert_no_replies(self.pg0, encap/arp*1, self.pg0)
+ rx = self.send_and_expect(self.pg0, encap/pkt*1, self.pg0)
+ self.assertEqual(rx[0][ICMP].type, 0) # echo reply
+
+ r = self.vapi.geneve_add_del_tunnel2(
+ is_add=0,
+ local_address=self.pg0.local_ip4,
+ remote_address=self.pg0.remote_ip4,
+ vni=vni)
+
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)