From e73b18be5ff5d5605da65014307580867573d8d8 Mon Sep 17 00:00:00 2001 From: Matthias Gatto Date: Mon, 4 May 2020 14:01:33 +0200 Subject: [PATCH 1/3] build: fix false positive error from old gcc Signed-off-by: Matthias Gatto --- src/brick.c | 2 +- src/nic.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/brick.c b/src/brick.c index 01982af6a..d86cf62af 100644 --- a/src/brick.c +++ b/src/brick.c @@ -763,7 +763,7 @@ int pg_brick_unlink_edge(struct pg_brick *west, { int i; int west_max; - int west_index; + int west_index = 0; struct pg_brick_edge *west_edge = NULL; if (!is_brick_valid(west)) { diff --git a/src/nic.c b/src/nic.c index 2180cc783..0bb141e74 100644 --- a/src/nic.c +++ b/src/nic.c @@ -50,7 +50,7 @@ static inline int pg_nic_port(char *ifname) return portid; #else - struct rte_dev_iterator it; + struct rte_dev_iterator it = {0}; if (rte_dev_probe(ifname) != 0) return -1; From 2b4b14290960f512129c95d341eb80974144a557 Mon Sep 17 00:00:00 2001 From: Matthias Gatto Date: Mon, 23 Mar 2020 13:35:26 +0100 Subject: [PATCH 2/3] vtep: add an option to have no multicast Signed-off-by: Matthias Gatto --- include/packetgraph/vtep.h | 5 ++++- src/vtep-impl.h | 38 +++++++++++++++++++++++--------------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/include/packetgraph/vtep.h b/include/packetgraph/vtep.h index 1a796bfa1..b4e3bde8a 100644 --- a/include/packetgraph/vtep.h +++ b/include/packetgraph/vtep.h @@ -34,7 +34,10 @@ enum pg_vtep_flags { * when incoming packets, just forward it */ PG_VTEP_NO_INNERMAC_CHECK = 2, PG_VTEP_FORCE_UPD_IPV6_CHECKSUM = 4, - PG_VTEP_ALL_OPTI = PG_VTEP_NO_COPY | PG_VTEP_NO_INNERMAC_CHECK + PG_VTEP_ALL_OPTI = PG_VTEP_NO_COPY | PG_VTEP_NO_INNERMAC_CHECK, + /* in this mode we don't do multicast, + dst mac must be add manually */ + PG_VTEP_NO_MULTICAST = 8 }; struct ether_addr; diff --git a/src/vtep-impl.h b/src/vtep-impl.h index dec384078..44baa1a0f 100644 --- a/src/vtep-impl.h +++ b/src/vtep-impl.h @@ -355,10 +355,12 @@ static inline int vtep_header_prepend(struct vtep_state *state, static inline int vtep_encapsulate(struct vtep_state *state, struct vtep_port *port, - struct rte_mbuf **pkts, uint64_t pkts_mask, + struct rte_mbuf **pkts, + uint64_t *maskp, struct pg_error **errp) { struct rte_mempool *mp = pg_get_mempool(); + uint64_t pkts_mask = *maskp; /* do the encapsulation */ for (; pkts_mask;) { @@ -388,6 +390,12 @@ static inline int vtep_encapsulate(struct vtep_state *state, unicast = 0; } + if (state->flags & PG_VTEP_NO_MULTICAST && !unicast) { + /* in this case all we can do is to skip the packet */ + *maskp &= ~(i + 1); + continue; + } + if (unlikely(!(state->flags & PG_VTEP_NO_COPY))) { tmp = rte_pktmbuf_clone(pkt, mp); if (unlikely(!tmp)) @@ -459,11 +467,15 @@ static inline int to_vtep(struct pg_brick *brick, enum pg_side from, if (unlikely(are_mac_tables_dead(port) && try_fix_tables(state, port, errp) < 0)) return -1; - /* if the port VNI is not set up ignore the packets */ - if (unlikely(!pg_is_multicast_ip(port->multicast_ip))) - return 0; - if (unlikely(vtep_encapsulate(state, port, pkts, pkts_mask, errp) < 0)) + if (!(state->flags & PG_VTEP_NO_MULTICAST)) { + /* if the port VNI is not set up ignore the packets */ + if (unlikely(!pg_is_multicast_ip(port->multicast_ip))) + return 0; + } + + if (unlikely(vtep_encapsulate(state, port, pkts, + &pkts_mask, errp) < 0)) return -1; ret = pg_brick_side_forward(s, from, state->pkts, pkts_mask, errp); @@ -795,7 +807,8 @@ static int do_add_vni(struct vtep_state *state, uint16_t edge_index, *errp = pg_error_new("port already attached to a vni"); return -1; } - if (unlikely(pg_is_multicast_ip(port->multicast_ip))) { + if (!(state->flags & PG_VTEP_NO_MULTICAST) && + unlikely(pg_is_multicast_ip(port->multicast_ip))) { *errp = pg_error_new("port alread have a mutlicast IP"); return -1; } @@ -806,7 +819,8 @@ static int do_add_vni(struct vtep_state *state, uint16_t edge_index, g_assert(!pg_mac_table_init(&port->mac_to_dst, &state->exeption_env)); g_assert(!pg_mac_table_init(&port->known_mac, &state->exeption_env)); - multicast_subscribe(state, port, multicast_ip, errp); + if (!(state->flags & PG_VTEP_NO_MULTICAST)) + multicast_subscribe(state, port, multicast_ip, errp); return 0; } @@ -827,8 +841,8 @@ static void do_remove_vni(struct vtep_state *state, if (!pg_is_multicast_ip(port->multicast_ip)) return; - multicast_unsubscribe(state, port, port->multicast_ip, - errp); + if (!(state->flags & PG_VTEP_NO_MULTICAST)) + multicast_unsubscribe(state, port, port->multicast_ip, errp); if (pg_error_is_set(errp)) return; @@ -1053,12 +1067,6 @@ int pg_vtep_add_vni_(struct pg_brick *brick, pg_ip_copy(multicast_ip, &tmp_ip); - if (!pg_is_multicast_ip(tmp_ip)) { - *errp = pg_error_new( - "Provided IP is not in the multicast range"); - return -1; - } - /* lookup for the vtep brick index */ found = 0; for (i = 0; i < brick->sides[side].max; i++) From e6475153fadee7177aa84be4d5a66e8b9bc3ebe2 Mon Sep 17 00:00:00 2001 From: Matthias Gatto Date: Tue, 24 Mar 2020 13:46:13 +0100 Subject: [PATCH 3/3] vtep: pg_vtep_add_vni_dst Signed-off-by: Matthias Gatto --- include/packetgraph/vtep.h | 10 +++++++ src/vtep-impl.h | 55 ++++++++++++++++++++++++++++++++++++++ tests/vtep/tests.c | 44 ++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) diff --git a/include/packetgraph/vtep.h b/include/packetgraph/vtep.h index b4e3bde8a..cb20c679e 100644 --- a/include/packetgraph/vtep.h +++ b/include/packetgraph/vtep.h @@ -96,6 +96,16 @@ int pg_vtep6_add_vni(struct pg_brick *brick, struct pg_brick *neighbor, uint32_t vni, uint8_t *multicast_ip, struct pg_error **errp); +int pg_vtep4_add_vni_dst(struct pg_brick *brick, uint32_t vni, + struct ether_addr *mac_vm, + struct ether_addr *dmac, uint32_t dip, + struct pg_error **errp); + +int pg_vtep6_add_vni_dst(struct pg_brick *brick, uint32_t vni, + struct ether_addr *mac_vm, + struct ether_addr *dmac, uint8_t *dip, + struct pg_error **errp); + #ifndef __cplusplus /** diff --git a/src/vtep-impl.h b/src/vtep-impl.h index 44baa1a0f..b00af25a4 100644 --- a/src/vtep-impl.h +++ b/src/vtep-impl.h @@ -1086,6 +1086,61 @@ int pg_vtep_add_vni_(struct pg_brick *brick, return 0; } +#define pg_vtep_add_vni_dst__(version) CATCAT(pg_vtep, version, _add_vni_dst) +#define pg_vtep_add_vni_dst_ pg_vtep_add_vni_dst__(IP_VERSION) + +int pg_vtep_add_vni_dst_(struct pg_brick *brick, uint32_t vni, + struct ether_addr *mac_vm, + struct ether_addr *dmac, IP_IN_TYPE dip, + struct pg_error **errp) +{ + struct vtep_state *state = pg_brick_get_state(brick, + struct vtep_state); + struct dest_addresses dst = {*dmac, +#if IP_VERSION == 4 + dip, +#else + {.word8 = {0}}, +#endif + state->vtep_tick}; + union pg_mac tmp = {.rte_addr = *mac_vm}; + struct vtep_port *ports = state->ports; + struct vtep_port *good_port = NULL; + struct pg_brick_side *s = &brick->sides[pg_flip_side(state->output)]; + + if (!brick) { + *errp = pg_error_new("brick is NULL"); + return -1; + } + + if (!is_vni_valid(vni)) { + *errp = pg_error_new("Invalid VNI"); + return -1; + } + +#if IP_VERSION != 4 + pg_ip_copy(dip, &dst.ip); +#endif + + for (int i = 0; i < s->nb; ++i) { + if (ports[i].vni == vni) { + good_port = &ports[i]; + break; + } + } + + if (!good_port) { + *errp = pg_error_new("can't find good VNI"); + return -1; + } + + pg_mac_table_elem_set(&good_port->mac_to_dst, tmp, &dst, + sizeof(struct dest_addresses)); + + return 0; +} + + #define pg_vtep_clean_all_mac__(version) \ CATCAT(pg_vtep, version, _clean_all_mac) #define pg_vtep_clean_all_mac_ pg_vtep_clean_all_mac__(IP_VERSION) diff --git a/tests/vtep/tests.c b/tests/vtep/tests.c index 8ab9a7387..4b9719ae6 100644 --- a/tests/vtep/tests.c +++ b/tests/vtep/tests.c @@ -1233,6 +1233,49 @@ static void test_vtep_lifetime(void) g_free(pkts); } +static void test_vtep_add_vni_dst(void) +{ + struct pg_error *error = NULL; + struct ether_addr multicast_mac1 = {{0,0,0,0,0,1}}; + struct ether_addr multicast_mac2 = {{0,0,0,0,0,2}}; + struct ether_addr mac_dst = {{0xaa}}; + struct rte_mbuf **pkts; + + pg_autobrick struct pg_brick *col = pg_collect_new("collect", &error); + pg_autobrick struct pg_brick *nop = pg_nop_new("n", &error); + pg_autobrick struct pg_brick *vtep = pg_vtep_new( + "vt", 1, PG_EAST_SIDE, 15, multicast_mac1, + PG_VTEP_DST_PORT, PG_VTEP_ALL_OPTI | PG_VTEP_NO_MULTICAST, + &error); + CHECK_ERROR(error); + + pg_brick_chained_links(&error, nop, vtep, col); + CHECK_ERROR(error); + + pg_vtep_add_vni(vtep, nop, 0, inet_addr("225.0.0.43"), &error); + CHECK_ERROR(error); + + pkts = pg_packets_create(-1LL); + pg_packets_append_ether(pkts, -1LL, + &(struct ether_addr){{0, 1}}, + &mac_dst, ETHER_TYPE_IPv4); + pg_packets_append_ipv4(pkts, -1LL, 0, -1, 10, 17); + + /* we test "no multicast", we didn't add any VNI DST + * so packets should be blocked */ + pg_brick_burst_to_east(vtep, 0, pkts, 1, &error); + g_assert(pg_brick_pkts_count_get(col, PG_EAST_SIDE) == 0); + + /* manually add vni DST */ + pg_vtep4_add_vni_dst(vtep, 0, &mac_dst, &multicast_mac2, + 1337, &error); + + pg_brick_burst_to_east(vtep, 0, pkts, -1LLU, &error); + g_assert(pg_brick_pkts_count_get(col, PG_EAST_SIDE) == 64); + pg_packets_free(pkts, pg_mask_firsts(NB_PKTS)); + +} + int main(int argc, char **argv) { int r; @@ -1248,6 +1291,7 @@ int main(int argc, char **argv) pg_test_add_func("/vtep/simple/no-copy", test_vtep_simple_no_copy); pg_test_add_func("/vtep/simple/all-opti", test_vtep_simple_all_opti); pg_test_add_func("/vtep/simple/lifetime", test_vtep_lifetime); + pg_test_add_func("/vtep/simple/add-vni-dst", test_vtep_add_vni_dst); pg_test_add_func("/vtep/vnis/all-opti", test_vtep_vnis_all_opti); pg_test_add_func("/vtep/vnis/no-copy", test_vtep_vnis_no_copy);