Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vtep: pg_vtep_add_vni_dst #529

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion include/packetgraph/vtep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -93,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

/**
Expand Down
2 changes: 1 addition & 1 deletion src/brick.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
2 changes: 1 addition & 1 deletion src/nic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
93 changes: 78 additions & 15 deletions src/vtep-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;) {
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}

Expand All @@ -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;
Expand Down Expand Up @@ -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++)
Expand All @@ -1078,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)
Expand Down
44 changes: 44 additions & 0 deletions tests/vtep/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down