static void test_brick_verify_re_link_monopole(void) { struct pg_brick *west_brick, *east_brick; struct pg_error *error = NULL; west_brick = pg_queue_new("q1", 1, &error); g_assert(!error); east_brick = pg_queue_new("q2", 1, &error); g_assert(!error); /* We link the 2 bricks */ pg_brick_link(west_brick, east_brick, &error); g_assert(!error); /* We unlink them */ pg_brick_unlink(west_brick, &error); g_assert(!error); /* We relink them to make sure unlink works */ pg_brick_link(west_brick, east_brick, &error); g_assert(!error); pg_brick_destroy(west_brick); pg_brick_destroy(east_brick); }
static void test_brick_core_verify_re_link(void) { struct pg_error *e = NULL; struct pg_brick *v = pg_nop_new("v", &e); g_assert(!e); struct pg_brick *f = pg_nop_new("f", &e); g_assert(!e); struct pg_brick *a = pg_nop_new("a", &e); g_assert(!e); struct pg_brick *s = pg_nop_new("s", &e); g_assert(!e); /* Initial state: v -- f -- a */ pg_brick_chained_links(&e, v, f, a); g_assert(!e); test_brick_sanity_check_expected(v, 0, 1); test_brick_sanity_check_expected(f, 1, 1); test_brick_sanity_check_expected(a, 1, 0); /* Unlink f */ pg_brick_unlink(f, &e); g_assert(!e); test_brick_sanity_check_expected(v, 0, 0); test_brick_sanity_check_expected(f, 0, 0); test_brick_sanity_check_expected(a, 0, 0); /* Link v and s */ pg_brick_link(v, s, &e); g_assert(!e); test_brick_sanity_check_expected(v, 0, 1); test_brick_sanity_check_expected(s, 1, 0); test_brick_sanity_check_expected(f, 0, 0); test_brick_sanity_check_expected(a, 0, 0); /* link the rest to have v -- s -- f -- a */ pg_brick_link(s, f, &e); g_assert(!e); test_brick_sanity_check_expected(v, 0, 1); test_brick_sanity_check_expected(s, 1, 1); test_brick_sanity_check_expected(f, 1, 0); test_brick_sanity_check_expected(a, 0, 0); pg_brick_link(f, a, &e); g_assert(!e); test_brick_sanity_check_expected(v, 0, 1); test_brick_sanity_check_expected(s, 1, 1); test_brick_sanity_check_expected(f, 1, 1); test_brick_sanity_check_expected(a, 1, 0); pg_brick_destroy(a); pg_brick_destroy(v); pg_brick_destroy(f); pg_brick_destroy(s); }
static void test_antispoof_rarp(void) { # include "rarp.c" const unsigned char *pkts[] = {pkt1}; int pkts_size[] = {15}; uint16_t pkts_nb = 1; struct ether_addr inside_mac; struct pg_brick *gen_west; struct pg_brick *antispoof; struct pg_brick *col_east; struct pg_error *error = NULL; uint16_t packet_count; uint16_t i; struct rte_mbuf *packet; uint64_t filtered_pkts_mask; pg_scan_ether_addr(&inside_mac, "00:23:df:ff:c9:23"); /* [generator>]--[antispoof]--[collector] */ gen_west = pg_packetsgen_new("gen_west", 1, 1, EAST_SIDE, &packet, 1, &error); g_assert(!error); antispoof = pg_antispoof_new("antispoof", 1, 1, EAST_SIDE, inside_mac, &error); g_assert(!error); col_east = pg_collect_new("col_east", 1, 1, &error); g_assert(!error); pg_brick_link(gen_west, antispoof, &error); g_assert(!error); pg_brick_link(antispoof, col_east, &error); g_assert(!error); /* replay traffic */ for (i = 0; i < pkts_nb; i++) { packet = build_packet(pkts[i], pkts_size[i]); pg_brick_poll(gen_west, &packet_count, &error); g_assert(!error); g_assert(packet_count == 1); pg_brick_west_burst_get(col_east, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == 0); rte_pktmbuf_free(packet); } pg_brick_destroy(gen_west); pg_brick_destroy(antispoof); pg_brick_destroy(col_east); }
int main(int argc, char **argv) { struct pg_error *error = NULL; struct pg_brick *nic, *app; struct pg_graph *graph; struct mydata pd; pd.pkt_count = 0; pg_start(argc, argv, &error); start_time = g_get_real_time(); if (pg_nic_port_count() < 1) { g_printf("No NIC port has been found, try adding --vdev=eth_pcap0,iface=eth0 arguments\n"); return 1; } nic = pg_nic_new_by_id("port 0", 0, &error); app = pg_rxtx_new("myapp", &rx_callback, &tx_callback, (void *) &pd); pg_brick_link(nic, app, &error); graph = pg_graph_new("example", nic, &error); while (42) if (pg_graph_poll(graph, &error) < 0) break; pg_error_print(error); pg_error_free(error); pg_graph_destroy(graph); pg_stop(); return 1; }
static void test_sorting_pmtud(void) { struct pg_error *error = NULL; struct pg_brick *pmtud; struct pg_brick *col_east; struct rte_mbuf **pkts; uint64_t pkts_mask; struct ether_addr eth = {{0}}; pkts = pg_packets_append_ether(pg_packets_create(pg_mask_firsts(64)), pg_mask_firsts(64), ð, ð, ETHER_TYPE_IPv4); pg_packets_append_ipv4(pkts, pg_mask_firsts(64), 1, 2, 0, 0); pg_packets_append_blank(pkts, pg_mask_firsts(32), 431 - sizeof(struct ipv4_hdr) - sizeof(struct ether_hdr)); pg_packets_append_blank(pkts, pg_mask_firsts(64) & ~pg_mask_firsts(32), 430 - sizeof(struct ipv4_hdr) - sizeof(struct ether_hdr)); pmtud = pg_pmtud_new("pmtud", PG_WEST_SIDE, 430, &error); g_assert(!error); col_east = pg_collect_new("col_east", &error); g_assert(!error); pg_brick_link(pmtud, col_east, &error); g_assert(!error); pg_brick_burst(pmtud, PG_WEST_SIDE, 0, pkts, pg_mask_firsts(64), &error); g_assert(!error); pg_brick_west_burst_get(col_east, &pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(pkts_mask) == 32); pg_brick_destroy(pmtud); pg_brick_destroy(col_east); pg_packets_free(pkts, pg_mask_firsts(64)); g_free(pkts); }
static void test_sorting_pmtud_df(void) { struct pg_error *error = NULL; struct pg_brick *pmtud; struct pg_brick *col_east; struct rte_mbuf **pkts; uint64_t pkts_mask; struct ether_addr eth = {{0}}; uint64_t buff[4] = {0, 0, 0, 0}; pkts = pg_packets_append_ether(pg_packets_create(pg_mask_firsts(64)), pg_mask_firsts(64), ð, ð, ETHER_TYPE_IPv4); pg_packets_append_ipv4(pkts, pg_mask_firsts(32), 1, 2, 0, 0); /* Initialise ip header to 0, this ensure that DF flag is not set*/ pg_packets_append_buf(pkts, pg_mask_firsts(64) & ~pg_mask_firsts(32), buff, sizeof(uint64_t) * 4); pg_packets_append_blank(pkts, pg_mask_firsts(64), 400); pmtud = pg_pmtud_new("pmtud", PG_WEST_SIDE, 430, &error); g_assert(!error); col_east = pg_collect_new("col_east", &error); g_assert(!error); pg_brick_link(pmtud, col_east, &error); g_assert(!error); pg_brick_burst(pmtud, PG_WEST_SIDE, 0, pkts, pg_mask_firsts(64), &error); g_assert(!error); pg_brick_west_burst_get(col_east, &pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(pkts_mask) == 32); pg_brick_destroy(pmtud); pg_brick_destroy(col_east); pg_packets_free(pkts, pg_mask_firsts(64)); g_free(pkts); }
static void inside_to_vxlan(void) { struct pg_error *error = NULL; struct pg_brick *vtep; struct pg_bench bench; struct pg_bench_stats stats; struct pg_brick *inside_nop; struct ether_addr mac1 = {{0x52,0x54,0x00,0x12,0x34,0x11}}; struct ether_addr mac2 = {{0x52,0x54,0x00,0x12,0x34,0x21}}; struct ether_addr mac3 = {{0x52,0x54,0x00,0x12,0x34,0x31}}; uint32_t len; pg_bench_init(&bench); vtep = pg_vtep_new("vtep", 1, 1, EAST_SIDE, inet_addr("192.168.0.1"), mac3, NO_PACKETS_CLEANUP | NO_COPY | NO_INNERMAC_CKECK, &error); g_assert(!error); inside_nop = pg_nop_new("nop-input", &error); bench.input_brick = inside_nop; bench.input_side = WEST_SIDE; bench.output_brick = vtep; bench.output_side = EAST_SIDE; bench.output_poll = false; bench.max_burst_cnt = 3000000; bench.count_brick = pg_nop_new("nop-inside", &error); bench.post_burst_op = remove_vtep_hdr; g_assert(!error); pg_brick_link(inside_nop, vtep, &error); g_assert(!error); pg_brick_link(vtep, bench.count_brick, &error); g_assert(!error); pg_vtep_add_vni(vtep, inside_nop, 0, inet_addr("224.0.0.5"), &error); g_assert(!error); bench.pkts_nb = 64; bench.pkts_mask = pg_mask_firsts(64); bench.pkts = pg_packets_create(bench.pkts_mask); bench.pkts = pg_packets_append_ether( bench.pkts, bench.pkts_mask, &mac1, &mac2, ETHER_TYPE_IPv4); len = sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr) + 1356; pg_packets_append_ipv4( bench.pkts, bench.pkts_mask, 0x000000EE, 0x000000CC, len, 17); bench.pkts = pg_packets_append_udp( bench.pkts, bench.pkts_mask, 1000, 2000, 1356); bench.pkts = pg_packets_append_blank(bench.pkts, bench.pkts_mask, 1356); //g_assert(pg_bench_run(&bench, &stats, &error)); pg_bench_run(&bench, &stats, &error); pg_error_print(error); /* We know that this brick burst all packets. */ stats.pkts_burst = stats.pkts_sent; printf("[inside] ==> [vtep] ==> [count] (VXLAN side)\n"); g_assert(pg_bench_print(&stats, NULL)); pg_packets_free(bench.pkts, bench.pkts_mask); pg_brick_destroy(vtep); pg_brick_destroy(inside_nop); pg_brick_destroy(bench.count_brick); }
static void firewall_filter_rules(enum pg_side dir) { struct pg_brick *gen; struct pg_brick *fw; struct pg_brick *col; struct pg_error *error = NULL; uint16_t i; int ret; static uint16_t nb = 30; struct rte_mbuf *packets[nb]; uint64_t filtered_pkts_mask; struct rte_mbuf **filtered_pkts; uint64_t bit; uint16_t packet_count; struct ip *ip; struct ether_hdr *eth; /* create and connect 3 bricks: generator -> firewall -> collector */ gen = pg_packetsgen_new("gen", 2, 2, pg_flip_side(dir), packets, nb, &error); g_assert(!error); fw = pg_firewall_new("fw", 2, 2, PG_NONE, &error); g_assert(!error); col = pg_collect_new("col", 2, 2, &error); g_assert(!error); /* revert link if needed */ if (dir == WEST_SIDE) { pg_brick_link(gen, fw, &error); g_assert(!error); pg_brick_link(fw, col, &error); g_assert(!error); } else { pg_brick_link(col, fw, &error); g_assert(!error); pg_brick_link(fw, gen, &error); g_assert(!error); } /* build some UDP packets mixed sources */ for (i = 0; i < nb; i++) switch (i % 3) { case 0: packets[i] = build_ip_packet("10.0.0.1", "10.0.0.255", i); break; case 1: packets[i] = build_ip_packet("10.0.0.2", "10.0.0.255", i); break; case 2: packets[i] = build_ip_packet("10.0.0.3", "10.0.0.255", i); break; } /* configure firewall to allow traffic from 10.0.0.1 */ ret = pg_firewall_rule_add(fw, "src host 10.0.0.1", dir, 0, &error); g_assert(!error); g_assert(ret == 0); ret = pg_firewall_reload(fw, &error); g_assert(ret < 0); g_assert(!error); /* let's burst ! */ pg_brick_poll(gen, &packet_count, &error); g_assert(!error); g_assert(packet_count == nb); /* check collect brick */ if (dir == WEST_SIDE) filtered_pkts = pg_brick_west_burst_get(col, &filtered_pkts_mask, &error); else filtered_pkts = pg_brick_east_burst_get(col, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == nb / 3); for (; filtered_pkts_mask;) { pg_low_bit_iterate_full(filtered_pkts_mask, bit, i); g_assert(i % 3 == 0); eth = rte_pktmbuf_mtod(filtered_pkts[i], struct ether_hdr*); ip = (struct ip *)(eth + 1); g_assert(ip->ip_src.s_addr == inet_addr("10.0.0.1")); } /* now allow packets from 10.0.0.2 */ ret = pg_firewall_rule_add(fw, "src host 10.0.0.2", dir, 0, &error); g_assert(!error); g_assert(ret == 0); ret = pg_firewall_reload(fw, &error); g_assert(ret < 0); g_assert(!error); /* let it goooo */ pg_brick_poll(gen, &packet_count, &error); g_assert(!error); g_assert(packet_count == nb); /* check collect brick */ if (dir == WEST_SIDE) filtered_pkts = pg_brick_west_burst_get(col, &filtered_pkts_mask, &error); else filtered_pkts = pg_brick_east_burst_get(col, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == nb * 2 / 3); for (; filtered_pkts_mask;) { pg_low_bit_iterate_full(filtered_pkts_mask, bit, i); g_assert(i % 3 == 0 || i % 3 == 1); eth = rte_pktmbuf_mtod(filtered_pkts[i], struct ether_hdr*); ip = (struct ip *)(eth + 1); g_assert(ip->ip_src.s_addr == inet_addr("10.0.0.1") || ip->ip_src.s_addr == inet_addr("10.0.0.2")); } /* test that flush really blocks */ pg_firewall_rule_flush(fw); ret = pg_firewall_reload(fw, &error); g_assert(!error); g_assert(ret < 0); /* let it goooo */ pg_brick_poll(gen, &packet_count, &error); g_assert(!error); g_assert(packet_count == nb); /* check collect brick */ if (dir == WEST_SIDE) filtered_pkts = pg_brick_west_burst_get(col, &filtered_pkts_mask, &error); else filtered_pkts = pg_brick_east_burst_get(col, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == 0); /* flush and only allow packets from 10.0.0.2 */ pg_firewall_rule_flush(fw); ret = pg_firewall_rule_add(fw, "src host 10.0.0.2", dir, 0, &error); g_assert(!error); g_assert(ret == 0); ret = pg_firewall_reload(fw, &error); g_assert(ret < 0); g_assert(!error); /* let it goooo */ pg_brick_poll(gen, &packet_count, &error); g_assert(!error); g_assert(packet_count == nb); /* check collect brick */ if (dir == WEST_SIDE) filtered_pkts = pg_brick_west_burst_get(col, &filtered_pkts_mask, &error); else filtered_pkts = pg_brick_east_burst_get(col, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == nb / 3); for (; filtered_pkts_mask;) { pg_low_bit_iterate_full(filtered_pkts_mask, bit, i); g_assert(i % 3 == 1); eth = rte_pktmbuf_mtod(filtered_pkts[i], struct ether_hdr*); ip = (struct ip *)(eth + 1); g_assert(ip->ip_src.s_addr == inet_addr("10.0.0.2")); } /* flush and make two rules in one */ pg_firewall_rule_flush(fw); ret = pg_firewall_rule_add(fw, "src host (10.0.0.1 or 10.0.0.2)", dir, 0, &error); g_assert(!error); g_assert(ret == 0); ret = pg_firewall_reload(fw, &error); g_assert(ret < 0); g_assert(!error); /* let it goooo */ pg_brick_poll(gen, &packet_count, &error); g_assert(!error); g_assert(packet_count == nb); /* check collect brick */ if (dir == WEST_SIDE) filtered_pkts = pg_brick_west_burst_get(col, &filtered_pkts_mask, &error); else filtered_pkts = pg_brick_east_burst_get(col, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == nb * 2 / 3); for (; filtered_pkts_mask;) { pg_low_bit_iterate_full(filtered_pkts_mask, bit, i); g_assert(i % 3 == 0 || i % 3 == 1); eth = rte_pktmbuf_mtod(filtered_pkts[i], struct ether_hdr*); ip = (struct ip *)(eth + 1); g_assert(ip->ip_src.s_addr == inet_addr("10.0.0.1") || ip->ip_src.s_addr == inet_addr("10.0.0.2")); } /* flush and revert rules, packets should not pass */ pg_firewall_rule_flush(fw); ret = pg_firewall_rule_add(fw, "src host (10.0.0.1)", pg_flip_side(dir), 0, &error); g_assert(!error); g_assert(ret == 0); ret = pg_firewall_reload(fw, &error); g_assert(ret < 0); g_assert(!error); /* let it goooo */ pg_brick_poll(gen, &packet_count, &error); g_assert(!error); g_assert(packet_count == nb); /* check collect brick */ if (dir == WEST_SIDE) filtered_pkts = pg_brick_west_burst_get(col, &filtered_pkts_mask, &error); else filtered_pkts = pg_brick_east_burst_get(col, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == 0); /* flush and allow packets from both sides */ pg_firewall_rule_flush(fw); ret = pg_firewall_rule_add(fw, "src host (10.0.0.1)", MAX_SIDE, 0, &error); g_assert(!error); g_assert(ret == 0); ret = pg_firewall_reload(fw, &error); g_assert(ret < 0); g_assert(!error); /* let it goooo */ pg_brick_poll(gen, &packet_count, &error); g_assert(!error); g_assert(packet_count == nb); if (dir == WEST_SIDE) filtered_pkts = pg_brick_west_burst_get(col, &filtered_pkts_mask, &error); else filtered_pkts = pg_brick_east_burst_get(col, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == nb / 3); for (; filtered_pkts_mask;) { pg_low_bit_iterate_full(filtered_pkts_mask, bit, i); g_assert(i % 3 == 0); eth = rte_pktmbuf_mtod(filtered_pkts[i], struct ether_hdr*); ip = (struct ip *)(eth + 1); g_assert(ip->ip_src.s_addr == inet_addr("10.0.0.1")); } /* inverse generator and collector to test both sides */ pg_brick_unlink(fw, &error); g_assert(!error); if (dir == WEST_SIDE) { pg_brick_link(col, fw, &error); g_assert(!error); pg_brick_link(fw, gen, &error); g_assert(!error); } else { pg_brick_link(gen, fw, &error); g_assert(!error); pg_brick_link(fw, col, &error); g_assert(!error); } /* let it goooo */ pg_brick_poll(gen, &packet_count, &error); g_assert(!error); g_assert(packet_count == nb); if (dir == WEST_SIDE) filtered_pkts = pg_brick_west_burst_get(col, &filtered_pkts_mask, &error); else filtered_pkts = pg_brick_east_burst_get(col, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == nb / 3); for (; filtered_pkts_mask;) { pg_low_bit_iterate_full(filtered_pkts_mask, bit, i); g_assert(i % 3 == 0); eth = rte_pktmbuf_mtod(filtered_pkts[i], struct ether_hdr*); ip = (struct ip *)(eth + 1); g_assert(ip->ip_src.s_addr == inet_addr("10.0.0.1")); } /* clean */ for (i = 0; i < nb; i++) rte_pktmbuf_free(packets[i]); pg_brick_destroy(gen); pg_brick_destroy(fw); pg_brick_destroy(col); }
static void test_nic_simple_flow(void) { struct pg_brick *nic_west, *nic_ring; int i = 0; int nb_iteration = 32; uint16_t nb_send_pkts; uint16_t total_send_pkts = 0; uint16_t total_get_pkts = 0; struct pg_error *error = NULL; struct pg_nic_stats info; /* create a chain of a few nop brick with collectors on each sides */ /* * [nic_west] ------- [nic_east] */ /* write rx pcap file (required bu pcap driver) */ const gchar pcap_in_file[] = { 212, 195, 178, 161, 2, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 1, 0, 0, 0}; g_assert(g_file_set_contents("in.pcap", pcap_in_file, sizeof(pcap_in_file), NULL)); nic_west = pg_nic_new("nic", "eth_pcap0,rx_pcap=in.pcap,tx_pcap=out.pcap", &error); CHECK_ERROR(error); nic_ring = pg_nic_new_by_id("nic", 0, &error); CHECK_ERROR(error); pg_brick_link(nic_west, nic_ring, &error); CHECK_ERROR(error); for (i = 0; i < nb_iteration * 6; ++i) { /* max pkts is the maximum nbr of packets rte_eth_burst_wrap can send */ max_pkts = i * 2; if (max_pkts > 64) max_pkts = 64; /*poll packets to east*/ pg_brick_poll(nic_west, &nb_send_pkts, &error); CHECK_ERROR(error); /* collect pkts on the east */ if (nb_send_pkts) { total_send_pkts += max_pkts; } /* check no pkts end here */ CHECK_ERROR(error); } pg_nic_get_stats(nic_ring, &info); g_assert(info.opackets == total_send_pkts); max_pkts = 64; for (i = 0; i < nb_iteration; ++i) { /* poll packet to the west */ pg_brick_poll(nic_ring, &nb_send_pkts, &error); CHECK_ERROR(error); total_get_pkts += nb_send_pkts; } /* This assert allow us to check nb_send_pkts*/ g_assert(total_get_pkts == total_send_pkts); g_assert(info.opackets == total_send_pkts); /* use packets_count in collect_west here to made * another check when merge*/ /* break the chain */ pg_brick_destroy(nic_west); pg_brick_destroy(nic_ring); /* remove pcap files */ g_assert(g_unlink("in.pcap") == 0); g_assert(g_unlink("out.pcap") == 0); }
static void test_queue_reset(void) { # define NB_PKTS 64 struct pg_error *error = NULL; struct pg_brick *queue1, *queue2, *collect; struct rte_mbuf **result_pkts; struct rte_mbuf *pkts[NB_PKTS]; uint64_t pkts_mask, i, j; uint16_t count = 0; struct rte_mempool *mbuf_pool = pg_get_mempool(); /** * Burst packets in queue1 and test reset of queue1 * [queue1] ~ [queue2]----[collect] */ queue1 = pg_queue_new("q1", 10, &error); CHECK_ERROR(error); queue2 = pg_queue_new("q2", 10, &error); CHECK_ERROR(error); collect = pg_collect_new("collect", 1, 1, &error); CHECK_ERROR(error); pg_brick_link(queue2, collect, &error); CHECK_ERROR(error); g_assert(!pg_queue_friend(queue1, queue2, &error)); CHECK_ERROR(error); for (i = 0; i < NB_PKTS; i++) { pkts[i] = rte_pktmbuf_alloc(mbuf_pool); g_assert(pkts[i]); pkts[i]->udata64 = i; pg_set_mac_addrs(pkts[i], "F0:F1:F2:F3:F4:F5", "E0:E1:E2:E3:E4:E5"); } for (j = 0; j < 100; j++) { for (i = 0; i < NB_PKTS; i++) pkts[i]->udata64 = i * j; /* burst and reset */ pg_brick_burst_to_east(queue1, 0, pkts, pg_mask_firsts(NB_PKTS), &error); CHECK_ERROR(error); g_assert(pg_queue_pressure(queue1) > 0); g_assert(!pg_brick_reset(queue1, &error)); g_assert(pg_queue_get_friend(queue1) == NULL); g_assert(pg_queue_get_friend(queue2) == NULL); g_assert(pg_queue_pressure(queue1) == 0); g_assert(pg_queue_pressure(queue2) == 0); pg_brick_poll(queue2, &count, &error); g_assert(!error); g_assert(count == 0); /* refriend and burst ok */ g_assert(!pg_queue_friend(queue1, queue2, &error)); g_assert(!error); g_assert(pg_queue_are_friend(queue1, queue2)); g_assert(!error); pg_brick_burst_to_east(queue1, 0, pkts, pg_mask_firsts(NB_PKTS), &error); CHECK_ERROR(error); g_assert(pg_queue_pressure(queue1) > 0); pg_brick_poll(queue2, &count, &error); g_assert(count == NB_PKTS); result_pkts = pg_brick_west_burst_get(collect, &pkts_mask, &error); CHECK_ERROR(error); g_assert(pkts_mask == pg_mask_firsts(NB_PKTS)); for (i = 0; i < NB_PKTS; i++) { g_assert(result_pkts[i]); g_assert(result_pkts[i]->udata64 == i * j); } pg_brick_reset(collect, &error); CHECK_ERROR(error); } /* clean */ for (i = 0; i < NB_PKTS; i++) rte_pktmbuf_free(pkts[i]); pg_brick_decref(queue1, &error); CHECK_ERROR(error); pg_brick_decref(queue2, &error); CHECK_ERROR(error); pg_brick_decref(collect, &error); CHECK_ERROR(error); # undef NB_PKTS }
static void test_brick_core_verify_multiple_link(void) { struct pg_brick *west_brick, *middle_brick, *east_brick; struct pg_brick_config *config = pg_brick_config_new("mybrick", 4, 4, PG_MULTIPOLE); uint32_t links_count; struct pg_error *error = NULL; west_brick = pg_brick_new("nop", config, &error); g_assert(!error); middle_brick = pg_brick_new("nop", config, &error); g_assert(!error); east_brick = pg_brick_new("nop", config, &error); g_assert(!error); /* create a few links */ pg_brick_link(west_brick, middle_brick, &error); g_assert(!error); pg_brick_link(west_brick, middle_brick, &error); g_assert(!error); pg_brick_link(middle_brick, east_brick, &error); g_assert(!error); pg_brick_link(middle_brick, east_brick, &error); g_assert(!error); pg_brick_link(middle_brick, east_brick, &error); g_assert(!error); /* sanity checks */ test_brick_sanity_check(west_brick); test_brick_sanity_check(middle_brick); test_brick_sanity_check(east_brick); /* check the link count */ links_count = pg_brick_links_count_get(west_brick, west_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(west_brick, middle_brick, &error); g_assert(!error); g_assert(links_count == 2); links_count = pg_brick_links_count_get(west_brick, east_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(middle_brick, middle_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(middle_brick, west_brick, &error); g_assert(!error); g_assert(links_count == 2); links_count = pg_brick_links_count_get(middle_brick, east_brick, &error); g_assert(!error); g_assert(links_count == 3); links_count = pg_brick_links_count_get(east_brick, east_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(east_brick, west_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(east_brick, middle_brick, &error); g_assert(!error); g_assert(links_count == 3); /* unlink the west brick */ pg_brick_unlink(west_brick, &error); /* sanity checks */ test_brick_sanity_check(west_brick); test_brick_sanity_check(middle_brick); test_brick_sanity_check(east_brick); /* check again */ links_count = pg_brick_links_count_get(west_brick, west_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(west_brick, middle_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(west_brick, east_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(middle_brick, middle_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(middle_brick, west_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(middle_brick, east_brick, &error); g_assert(!error); g_assert(links_count == 3); links_count = pg_brick_links_count_get(east_brick, east_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(east_brick, west_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(east_brick, middle_brick, &error); g_assert(!error); g_assert(links_count == 3); /* unlink the east brick */ pg_brick_unlink(east_brick, &error); g_assert(!error); /* sanity checks */ test_brick_sanity_check(west_brick); test_brick_sanity_check(middle_brick); test_brick_sanity_check(east_brick); /* check again */ links_count = pg_brick_links_count_get(west_brick, west_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(west_brick, middle_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(west_brick, east_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(middle_brick, middle_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(middle_brick, west_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(middle_brick, east_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(east_brick, east_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(east_brick, west_brick, &error); g_assert(!error); g_assert(links_count == 0); links_count = pg_brick_links_count_get(east_brick, middle_brick, &error); g_assert(!error); g_assert(links_count == 0); /* destroy */ pg_brick_decref(west_brick, &error); g_assert(!error); pg_brick_decref(middle_brick, &error); g_assert(!error); pg_brick_decref(east_brick, &error); g_assert(!error); pg_brick_config_free(config); }
static void inside_to_vxlan(int argc, char **argv) { struct pg_error *error = NULL; struct pg_brick *vtep; struct pg_bench bench; struct pg_bench_stats stats; struct pg_brick *inside_nop; struct ether_addr mac1 = {{0x52,0x54,0x00,0x12,0x34,0x11}}; struct ether_addr mac2 = {{0x52,0x54,0x00,0x12,0x34,0x21}}; struct ether_addr mac3 = {{0x52,0x54,0x00,0x12,0x34,0x31}}; uint32_t len; g_assert(!pg_bench_init(&bench, "vtep inside to vxlan", argc, argv, &error)); vtep = pg_vtep_new("vtep", 1, 1, EAST_SIDE, inet_addr("192.168.0.1"), mac3, PG_VTEP_DST_PORT, ALL_OPTI, &error); g_assert(!error); inside_nop = pg_nop_new("nop-input", &error); bench.input_brick = inside_nop; bench.input_side = WEST_SIDE; bench.output_brick = vtep; bench.output_side = EAST_SIDE; bench.output_poll = false; bench.max_burst_cnt = 3000000; bench.count_brick = pg_nop_new("nop-inside", &error); bench.post_burst_op = remove_vtep_hdr; g_assert(!error); pg_brick_link(inside_nop, vtep, &error); g_assert(!error); pg_brick_link(vtep, bench.count_brick, &error); g_assert(!error); pg_vtep_add_vni(vtep, inside_nop, 0, inet_addr("224.0.0.5"), &error); g_assert(!error); bench.pkts_nb = 64; bench.pkts_mask = pg_mask_firsts(64); bench.pkts = pg_packets_create(bench.pkts_mask); bench.pkts = pg_packets_append_ether( bench.pkts, bench.pkts_mask, &mac1, &mac2, ETHER_TYPE_IPv4); len = sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr) + 1356; pg_packets_append_ipv4( bench.pkts, bench.pkts_mask, 0x000000EE, 0x000000CC, len, 17); bench.pkts = pg_packets_append_udp( bench.pkts, bench.pkts_mask, 1000, PG_VTEP_DST_PORT, 1356); bench.pkts = pg_packets_append_blank(bench.pkts, bench.pkts_mask, 1356); bench.brick_full_burst = 1; //g_assert(pg_bench_run(&bench, &stats, &error)); pg_bench_run(&bench, &stats, &error); g_assert(!pg_error_is_set(&error)); pg_bench_print(&stats); pg_packets_free(bench.pkts, bench.pkts_mask); pg_brick_destroy(vtep); pg_brick_destroy(inside_nop); pg_brick_destroy(bench.count_brick); }
static void vxlan_to_inside(int flags, const char *title, int argc, char **argv) { struct pg_error *error = NULL; struct pg_brick *vtep; struct pg_bench bench; struct pg_bench_stats stats; struct pg_brick *outside_nop; struct ether_addr mac3 = {{0x52,0x54,0x00,0x12,0x34,0x31}}; struct ether_addr mac4 = {{0x52,0x54,0x00,0x12,0x34,0x41}}; static struct ether_addr mac_vtep = {{0xb0,0xb1,0xb2,0xb3,0xb4,0xb5}}; uint32_t len; vtep = pg_vtep_new("vtep", 1, 1, WEST_SIDE, 0x000000EE, mac_vtep, PG_VTEP_DST_PORT, flags, &error); g_assert(!error); g_assert(!pg_bench_init(&bench, title, argc, argv, &error)); outside_nop = pg_nop_new("nop-outside", &error); bench.input_brick = outside_nop; bench.input_side = WEST_SIDE; bench.output_brick = vtep; bench.output_side = EAST_SIDE; bench.output_poll = false; bench.max_burst_cnt = 1000000; bench.count_brick = pg_nop_new("nop-bench", &error); if (flags & NO_COPY) bench.post_burst_op = add_vtep_hdr; g_assert(!error); pg_brick_link(outside_nop, vtep, &error); g_assert(!error); pg_brick_link(vtep, bench.count_brick, &error); g_assert(!error); pg_vtep_add_vni(vtep, bench.count_brick, 1, inet_addr("224.0.0.1"), &error); g_assert(!pg_error_is_set(&error)); if (pg_vtep_add_mac(vtep, 1, &mac4, &error) < 0) pg_error_print(error); g_assert(!pg_error_is_set(&error)); pg_vtep_add_mac(vtep, 1, &mac3, &error); if (pg_vtep_add_mac(vtep, 1, &mac4, &error) < 0) pg_error_print(error); g_assert(!pg_error_is_set(&error)); bench.pkts_nb = 64; bench.pkts_mask = pg_mask_firsts(64); bench.pkts = pg_packets_create(bench.pkts_mask); bench.pkts = pg_packets_append_ether( bench.pkts, bench.pkts_mask, &mac_vtep, &mac_vtep, ETHER_TYPE_IPv4); bench.brick_full_burst = 1; len = sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr) + sizeof(struct ether_hdr) + 1400; pg_packets_append_ipv4( bench.pkts, bench.pkts_mask, 0x000000EE, 0x000000CC, len, 17); bench.pkts = pg_packets_append_udp( bench.pkts, bench.pkts_mask, 1000, PG_VTEP_DST_PORT, 1400); pg_packets_append_vxlan(bench.pkts, bench.pkts_mask, 1); bench.pkts = pg_packets_append_ether( bench.pkts, bench.pkts_mask, &mac3, &mac4, ETHER_TYPE_IPv4); bench.pkts = pg_packets_append_blank(bench.pkts, bench.pkts_mask, 1400); memcpy(vxlan_hdr, rte_pktmbuf_mtod(bench.pkts[0], void *), len - 1400); vxlan_hdr[sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr) + sizeof(struct ether_hdr)] = '\0'; g_assert(pg_bench_run(&bench, &stats, &error) == 0); pg_bench_print(&stats); pg_packets_free(bench.pkts, bench.pkts_mask); pg_brick_destroy(vtep); pg_brick_destroy(outside_nop); pg_brick_destroy(bench.count_brick); }
static void firewall_replay(const unsigned char *pkts[], int pkts_nb, int *pkts_size) { struct pg_brick *gen_west, *gen_east; struct pg_brick *fw; struct pg_brick *col_west, *col_east; struct pg_error *error = NULL; uint16_t i, packet_count; struct rte_mbuf *packet; struct ether_hdr *eth; uint64_t filtered_pkts_mask; struct rte_mbuf **filtered_pkts; struct ether_addr tmp_addr; int ret; /* have some collectors and generators on each sides * [collector]--[generator>]--[firewall]--[<generator]--[collector] * 10.0.2.15 173.194.40.111 * 8:0:27:b6:5:16 52:54:0:12:35:2 */ gen_west = pg_packetsgen_new("gen_west", 1, 1, EAST_SIDE, &packet, 1, &error); g_assert(!error); gen_east = pg_packetsgen_new("gen_east", 1, 1, WEST_SIDE, &packet, 1, &error); g_assert(!error); fw = pg_firewall_new("fw", 1, 1, PG_NONE, &error); g_assert(!error); col_west = pg_collect_new("col_west", 1, 1, &error); g_assert(!error); col_east = pg_collect_new("col_east", 1, 1, &error); g_assert(!error); pg_brick_link(col_west, gen_west, &error); g_assert(!error); pg_brick_link(gen_west, fw, &error); g_assert(!error); pg_brick_link(fw, gen_east, &error); g_assert(!error); pg_brick_link(gen_east, col_east, &error); g_assert(!error); /* open all traffic of 10.0.2.15 from the west side of the firewall * returning traffic should be allowed due to STATEFUL option */ ret = pg_firewall_rule_add(fw, "src host 10.0.2.15", WEST_SIDE, 1, &error); g_assert(!error); g_assert(ret == 0); ret = pg_firewall_reload(fw, &error); g_assert(!error); g_assert(ret < 0); /* replay traffic */ for (i = 0; i < pkts_nb; i++) { struct ip *ip; packet = build_packet(pkts[i], pkts_size[i]); eth = rte_pktmbuf_mtod(packet, struct ether_hdr*); ip = (struct ip *)(eth + 1); if (ip->ip_src.s_addr == inet_addr("10.0.2.15")) { pg_brick_poll(gen_west, &packet_count, &error); g_assert(!error); g_assert(packet_count == 1); filtered_pkts = pg_brick_west_burst_get(col_east, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == 1); /* check eth source address */ eth = rte_pktmbuf_mtod(filtered_pkts[0], struct ether_hdr*); pg_scan_ether_addr(&tmp_addr, "08:00:27:b6:05:16"); g_assert(is_same_ether_addr(ð->s_addr, &tmp_addr)); /* check ip source address */ ip = (struct ip *)(eth + 1); g_assert(ip->ip_src.s_addr == inet_addr("10.0.2.15")); } else if (ip->ip_src.s_addr == inet_addr("173.194.40.111")) {
static void test_antispoof_generic(const unsigned char **pkts, int *pkts_size, uint16_t pkts_nb, struct ether_addr inside_mac, uint32_t inside_ip) { struct pg_brick *gen_west; struct pg_brick *antispoof; struct pg_brick *col_east; struct pg_error *error = NULL; uint16_t packet_count; uint16_t i; struct rte_mbuf *packet; uint64_t filtered_pkts_mask; struct rte_mbuf **filtered_pkts; /* [generator>]--[antispoof]--[collector] */ gen_west = pg_packetsgen_new("gen_west", 1, 1, EAST_SIDE, &packet, 1, &error); g_assert(!error); antispoof = pg_antispoof_new("antispoof", 1, 1, EAST_SIDE, inside_mac, &error); g_assert(!error); col_east = pg_collect_new("col_east", 1, 1, &error); g_assert(!error); pg_brick_link(gen_west, antispoof, &error); g_assert(!error); pg_brick_link(antispoof, col_east, &error); g_assert(!error); /* enable ARP antispoof with the correct IP */ pg_antispoof_arp_enable(antispoof, inside_ip); /* replay traffic */ for (i = 0; i < pkts_nb; i++) { packet = build_packet(pkts[i], pkts_size[i]); pg_brick_poll(gen_west, &packet_count, &error); g_assert(!error); g_assert(packet_count == 1); filtered_pkts = pg_brick_west_burst_get(col_east, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == 1); pg_packets_free(filtered_pkts, filtered_pkts_mask); rte_pktmbuf_free(packet); } /* set another IP, should not pass */ inside_ip = htobe32(IPv4(42, 0, 42, 0)); pg_antispoof_arp_enable(antispoof, inside_ip); /* replay traffic */ for (i = 0; i < pkts_nb; i++) { packet = build_packet(pkts[i], pkts_size[i]); pg_brick_poll(gen_west, &packet_count, &error); g_assert(!error); g_assert(packet_count == 1); filtered_pkts = pg_brick_west_burst_get(col_east, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == 0); pg_packets_free(filtered_pkts, filtered_pkts_mask); rte_pktmbuf_free(packet); } pg_brick_destroy(gen_west); pg_brick_destroy(antispoof); pg_brick_destroy(col_east); }
static void test_pg_antispoof_arp_disable(void) { # include "arp_request.c" const unsigned char *pkts[] = {pkt1}; int pkts_size[] = {42}; uint16_t pkts_nb = 1; struct ether_addr inside_mac; uint32_t inside_ip; struct pg_brick *gen_west; struct pg_brick *antispoof; struct pg_brick *col_east; struct pg_error *error = NULL; uint16_t packet_count; uint16_t i; struct rte_mbuf *packet; uint64_t filtered_pkts_mask; struct rte_mbuf **filtered_pkts; pg_scan_ether_addr(&inside_mac, "00:e0:81:d5:02:91"); inside_ip = htobe32(IPv4(0, 0, 0, 42)); /* [generator>]--[antispoof]--[collector] */ gen_west = pg_packetsgen_new("gen_west", 1, 1, EAST_SIDE, &packet, 1, &error); g_assert(!error); antispoof = pg_antispoof_new("antispoof", 1, 1, EAST_SIDE, inside_mac, &error); g_assert(!error); col_east = pg_collect_new("col_east", 1, 1, &error); g_assert(!error); pg_brick_link(gen_west, antispoof, &error); g_assert(!error); pg_brick_link(antispoof, col_east, &error); g_assert(!error); /* enable ARP antispoof with a wrong IP */ pg_antispoof_arp_enable(antispoof, inside_ip); /* replay traffic */ for (i = 0; i < pkts_nb; i++) { packet = build_packet(pkts[i], pkts_size[i]); pg_brick_poll(gen_west, &packet_count, &error); g_assert(!error); g_assert(packet_count == 1); filtered_pkts = pg_brick_west_burst_get(col_east, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == 0); pg_packets_free(filtered_pkts, filtered_pkts_mask); rte_pktmbuf_free(packet); } /* disable ARP antispoof, should now pass */ pg_antispoof_arp_disable(antispoof); /* replay traffic */ for (i = 0; i < pkts_nb; i++) { packet = build_packet(pkts[i], pkts_size[i]); pg_brick_poll(gen_west, &packet_count, &error); g_assert(!error); g_assert(packet_count == 1); filtered_pkts = pg_brick_west_burst_get(col_east, &filtered_pkts_mask, &error); g_assert(!error); g_assert(pg_mask_count(filtered_pkts_mask) == 1); pg_packets_free(filtered_pkts, filtered_pkts_mask); rte_pktmbuf_free(packet); } pg_brick_destroy(gen_west); pg_brick_destroy(antispoof); pg_brick_destroy(col_east); }
static void test_brick_core_link(void) { struct pg_error *error = NULL; struct pg_brick *west_brick, *middle_brick, *east_brick; struct pg_brick_config *config = pg_brick_config_new("mybrick", 4, 4, PG_MULTIPOLE); int64_t refcount; int ret; west_brick = pg_brick_new("nop", config, &error); g_assert(west_brick); g_assert(!error); middle_brick = pg_brick_new("nop", config, &error); g_assert(middle_brick); g_assert(!error); east_brick = pg_brick_new("nop", config, &error); g_assert(east_brick); g_assert(!error); ret = pg_brick_link(west_brick, middle_brick, &error); g_assert(ret == 0); g_assert(!error); ret = pg_brick_link(middle_brick, east_brick, &error); g_assert(ret == 0); g_assert(!error); refcount = pg_brick_refcount(west_brick); g_assert(refcount == 2); refcount = pg_brick_refcount(middle_brick); g_assert(refcount == 3); refcount = pg_brick_refcount(east_brick); g_assert(refcount == 2); pg_brick_unlink(west_brick, &error); g_assert(!error); refcount = pg_brick_refcount(west_brick); g_assert(refcount == 1); refcount = pg_brick_refcount(middle_brick); g_assert(refcount == 2); refcount = pg_brick_refcount(east_brick); g_assert(refcount == 2); pg_brick_unlink(east_brick, &error); g_assert(!error); refcount = pg_brick_refcount(west_brick); g_assert(refcount == 1); refcount = pg_brick_refcount(middle_brick); g_assert(refcount == 1); refcount = pg_brick_refcount(east_brick); g_assert(refcount == 1); /* destroy */ pg_brick_decref(west_brick, &error); g_assert(!error); pg_brick_decref(middle_brick, &error); g_assert(!error); pg_brick_decref(east_brick, &error); g_assert(!error); pg_brick_config_free(config); }
int main(int argc, char **argv) { struct pg_error *error = NULL; struct pg_brick *fw; struct pg_brick *nic_west, *nic_east; uint16_t nb_send_pkts; uint64_t total; struct timeval start, end; int i; pg_start(argc, argv, &error); CHECK_ERROR(error); g_assert(rte_eth_dev_count() >= 2); nic_west = pg_nic_new_by_id("port 0", 1, 1, WEST_SIDE, 0, &error); CHECK_ERROR(error); fw = pg_firewall_new("fw", 1, 1, PG_NO_CONN_WORKER, &error); pg_firewall_thread_register(fw); CHECK_ERROR(error); nic_east = pg_nic_new_by_id("port 1", 1, 1, EAST_SIDE, 1, &error); CHECK_ERROR(error); pg_brick_link(nic_west, fw, &error); CHECK_ERROR(error); pg_brick_link(fw, nic_east, &error); CHECK_ERROR(error); g_assert(!pg_firewall_rule_add(fw, "tcp portrange 50-60", MAX_SIDE, 1, &error)); CHECK_ERROR(error); g_assert(!pg_firewall_rule_add(fw, "icmp", MAX_SIDE, 1, &error)); CHECK_ERROR(error); g_assert(!pg_firewall_reload(fw, &error)); CHECK_ERROR(error); for (;;) { gettimeofday(&start, 0); total = 0; for (i = 0; i < LOOPS; i++) { g_assert(pg_brick_poll(nic_west, &nb_send_pkts, &error)); usleep(1); total += nb_send_pkts; g_assert(pg_brick_poll(nic_east, &nb_send_pkts, &error)); total += nb_send_pkts; usleep(1); } gettimeofday(&end, 0); usleep(100); printf("time in us: for %i loops: %lu\ntotal %"PRIu64"\n", LOOPS, (end.tv_sec * 1000000 + end.tv_usec) - (start.tv_sec * 1000000 + start.tv_usec), total); pg_firewall_gc(fw); } pg_stop(); return 0; }
static void test_nic_simple_flow(void) { struct pg_brick *nic_west, *nic_ring; int i = 0; int nb_iteration = 32; uint16_t nb_send_pkts; uint16_t total_send_pkts = 0; uint16_t total_get_pkts = 0; struct pg_error *error = NULL; struct pg_nic_stats info; gchar *tmp; /* create a chain of a few nop brick with collectors on each sides */ /* * [nic_west] ------- [nic_east] */ tmp = g_strdup_printf("eth_pcap0,rx_pcap=%s,tx_pcap=out.pcap", glob_pcap_in); nic_west = pg_nic_new("nic", tmp, &error); g_free(tmp); CHECK_ERROR(error); nic_ring = pg_nic_new_by_id("nic", 0, &error); CHECK_ERROR(error); pg_brick_link(nic_west, nic_ring, &error); CHECK_ERROR(error); for (i = 0; i < nb_iteration * 6; ++i) { /* max pkts is the maximum nbr of packets rte_eth_burst_wrap can send */ max_pkts = i * 2; if (max_pkts > 64) max_pkts = 64; /*poll packets to east*/ pg_brick_poll(nic_west, &nb_send_pkts, &error); CHECK_ERROR(error); /* collect pkts on the east */ if (nb_send_pkts) { total_send_pkts += max_pkts; } /* check no pkts end here */ CHECK_ERROR(error); } pg_nic_get_stats(nic_ring, &info); g_assert(info.opackets == total_send_pkts); max_pkts = 64; for (i = 0; i < nb_iteration; ++i) { /* poll packet to the west */ pg_brick_poll(nic_ring, &nb_send_pkts, &error); CHECK_ERROR(error); total_get_pkts += nb_send_pkts; } /* This assert allow us to check nb_send_pkts*/ g_assert(total_get_pkts == total_send_pkts); g_assert(info.opackets == total_send_pkts); /* use packets_count in collect_west here to made * another check when merge*/ /* break the chain */ pg_brick_destroy(nic_west); pg_brick_destroy(nic_ring); }
static void test_brick_flow_west(void) { struct pg_brick_config *config = pg_brick_config_new("mybrick", 4, 4); struct pg_brick *brick1, *brick2, *collect_west, *collect_east; struct rte_mbuf mbufs[NB_PKTS]; struct rte_mbuf **result_pkts; struct rte_mbuf *pkts[NB_PKTS]; uint16_t i; uint64_t pkts_mask; struct pg_error *error = NULL; /* prepare the packets to send */ for (i = 0; i < NB_PKTS; i++) { mbufs[i].udata64 = i; pkts[i] = &mbufs[i]; } /* create a chain of a few nop brick with collectors on each sides */ brick1 = pg_brick_new("nop", config, &error); g_assert(!error); brick2 = pg_brick_new("nop", config, &error); g_assert(!error); collect_west = pg_brick_new("collect", config, &error); g_assert(!error); g_assert(collect_west); collect_east = pg_brick_new("collect", config, &error); g_assert(!error); g_assert(collect_east); pg_brick_link(collect_west, brick1, &error); g_assert(!error); pg_brick_link(brick1, brick2, &error); g_assert(!error); pg_brick_link(brick2, collect_east, &error); g_assert(!error); /* send a pkts to the west from the eastest nope brick */ pg_brick_burst_to_west(brick2, 0, pkts, NB_PKTS, pg_mask_firsts(NB_PKTS), &error); g_assert(!error); /* check pkts counter */ g_assert(pg_brick_pkts_count_get(collect_east, WEST_SIDE) == 0); g_assert(pg_brick_pkts_count_get(collect_east, EAST_SIDE) == 0); g_assert(pg_brick_pkts_count_get(collect_west, WEST_SIDE) == 3); g_assert(pg_brick_pkts_count_get(collect_west, EAST_SIDE) == 0); g_assert(pg_brick_pkts_count_get(brick1, WEST_SIDE) == 3); g_assert(pg_brick_pkts_count_get(brick1, EAST_SIDE) == 0); g_assert(pg_brick_pkts_count_get(brick2, WEST_SIDE) == 3); g_assert(pg_brick_pkts_count_get(brick2, EAST_SIDE) == 0); /* check no packet ended on the east */ result_pkts = pg_brick_west_burst_get(collect_east, &pkts_mask, &error); g_assert(!error); g_assert(!pkts_mask); g_assert(!result_pkts); result_pkts = pg_brick_east_burst_get(collect_east, &pkts_mask, &error); g_assert(!error); g_assert(!pkts_mask); g_assert(!result_pkts); /* collect pkts on the west */ result_pkts = pg_brick_west_burst_get(collect_west, &pkts_mask, &error); g_assert(!error); g_assert(!pkts_mask); g_assert(!result_pkts); result_pkts = pg_brick_east_burst_get(collect_west, &pkts_mask, &error); g_assert(!error); g_assert(pkts_mask == pg_mask_firsts(NB_PKTS)); g_assert(result_pkts); for (i = 0; i < NB_PKTS; i++) g_assert(result_pkts[i]->udata64 == i); /* break the chain */ pg_brick_unlink(brick1, &error); g_assert(!error); pg_brick_unlink(brick2, &error); g_assert(!error); pg_brick_unlink(collect_west, &error); g_assert(!error); pg_brick_unlink(collect_east, &error); g_assert(!error); /* destroy */ pg_brick_decref(brick1, &error); g_assert(!error); pg_brick_decref(brick2, &error); g_assert(!error); pg_brick_decref(collect_west, &error); g_assert(!error); pg_brick_decref(collect_east, &error); g_assert(!error); pg_brick_config_free(config); }
static void vxlan_to_inside(void) { struct pg_error *error = NULL; struct pg_brick *vtep; struct pg_bench bench; struct pg_bench_stats stats; struct pg_brick *outside_nop; struct ether_addr mac3 = {{0x52,0x54,0x00,0x12,0x34,0x31}}; struct ether_addr mac4 = {{0x52,0x54,0x00,0x12,0x34,0x41}}; static struct ether_addr mac_vtep = {{0xb0,0xb1,0xb2,0xb3,0xb4,0xb5}}; uint32_t len; vtep = pg_vtep_new("vtep", 1, 1, WEST_SIDE, 0x000000EE, mac_vtep, NO_INNERMAC_CKECK | NO_PACKETS_CLEANUP | NO_COPY, &error); g_assert(!error); pg_bench_init(&bench); outside_nop = pg_nop_new("nop-outside", &error); bench.input_brick = outside_nop; bench.input_side = WEST_SIDE; bench.output_brick = vtep; bench.output_side = EAST_SIDE; bench.output_poll = false; bench.max_burst_cnt = 1000000; bench.count_brick = pg_nop_new("nop-bench", &error); bench.post_burst_op = add_vtep_hdr; g_assert(!error); pg_brick_link(outside_nop, vtep, &error); g_assert(!error); pg_brick_link(vtep, bench.count_brick, &error); g_assert(!error); pg_vtep_add_vni(vtep, bench.count_brick, 1, inet_addr("224.0.0.1"), &error); pg_error_print(error); g_assert(!error); bench.pkts_nb = 64; bench.pkts_mask = pg_mask_firsts(64); bench.pkts = pg_packets_create(bench.pkts_mask); bench.pkts = pg_packets_append_ether( bench.pkts, bench.pkts_mask, &mac_vtep, &mac_vtep, ETHER_TYPE_IPv4); len = sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr) + sizeof(struct ether_hdr) + 1400; pg_packets_append_ipv4( bench.pkts, bench.pkts_mask, 0x000000EE, 0x000000CC, len, 17); bench.pkts = pg_packets_append_udp( bench.pkts, bench.pkts_mask, 1000, 2000, 1400); pg_packets_append_vxlan(bench.pkts, bench.pkts_mask, 1); bench.pkts = pg_packets_append_ether( bench.pkts, bench.pkts_mask, &mac3, &mac4, ETHER_TYPE_IPv4); bench.pkts = pg_packets_append_blank(bench.pkts, bench.pkts_mask, 1400); memcpy(vxlan_hdr, rte_pktmbuf_mtod(bench.pkts[0], void *), len - 1400); vxlan_hdr[sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr) + sizeof(struct ether_hdr)] = '\0'; g_assert(pg_bench_run(&bench, &stats, &error)); /* We know that this brick burst all packets. */ stats.pkts_burst = stats.pkts_sent; printf("[outside] ==> [vtep] ==> [count] (no VXLAN side)\n"); g_assert(pg_bench_print(&stats, NULL)); pg_packets_free(bench.pkts, bench.pkts_mask); pg_brick_destroy(vtep); pg_brick_destroy(outside_nop); pg_brick_destroy(bench.count_brick); }
/* this test harness a Linux guest to check that packet are send and received * by the vhost brick. An ethernet bridge inside the guest will forward packets * between the two vhost-user virtio interfaces. */ static void test_vhost_flow_(int qemu_exit_signal) { const char mac_addr_0[18] = "52:54:00:12:34:11"; const char mac_addr_1[18] = "52:54:00:12:34:12"; struct rte_mempool *mbuf_pool = pg_get_mempool(); struct pg_brick *vhost_0, *vhost_1, *collect; struct rte_mbuf *pkts[PG_MAX_PKTS_BURST]; const char *socket_path_0, *socket_path_1; struct pg_error *error = NULL; struct rte_mbuf **result_pkts; int ret, qemu_pid, i; uint64_t pkts_mask; /* start vhost */ ret = pg_vhost_start("/tmp", &error); g_assert(ret == 0); g_assert(!error); /* instanciate brick */ vhost_0 = pg_vhost_new("vhost-0", &error); g_assert(!error); g_assert(vhost_0); vhost_1 = pg_vhost_new("vhost-1", &error); g_assert(!error); g_assert(vhost_1); collect = pg_collect_new("collect", &error); g_assert(!error); g_assert(collect); /* build the graph */ pg_brick_link(collect, vhost_1, &error); g_assert(!error); /* spawn first QEMU */ socket_path_0 = pg_vhost_socket_path(vhost_0, &error); g_assert(!error); g_assert(socket_path_0); socket_path_1 = pg_vhost_socket_path(vhost_1, &error); g_assert(!error); g_assert(socket_path_1); qemu_pid = pg_util_spawn_qemu(socket_path_0, socket_path_1, mac_addr_0, mac_addr_1, glob_vm_path, glob_vm_key_path, glob_hugepages_path, &error); g_assert(!error); g_assert(qemu_pid); /* Prepare VM's bridge. */ # define SSH(c) \ g_assert(pg_util_ssh("localhost", ssh_port_id, glob_vm_key_path, c) == 0) SSH("brctl addbr br0"); SSH("ifconfig br0 up"); SSH("ifconfig ens4 up"); SSH("ifconfig ens5 up"); SSH("brctl addif br0 ens4"); SSH("brctl addif br0 ens5"); SSH("brctl setfd br0 0"); SSH("brctl stp br0 off"); # undef SSH ssh_port_id++; /* prepare packet to send */ for (i = 0; i < NB_PKTS; i++) { pkts[i] = rte_pktmbuf_alloc(mbuf_pool); g_assert(pkts[i]); rte_pktmbuf_append(pkts[i], ETHER_MIN_LEN); /* set random dst/src mac address so the linux guest bridge * will not filter them */ pg_set_mac_addrs(pkts[i], "52:54:00:12:34:15", "52:54:00:12:34:16"); /* set size */ pg_set_ether_type(pkts[i], ETHER_MIN_LEN - ETHER_HDR_LEN - 4); } /* send packet to the guest via one interface */ pg_brick_burst_to_east(vhost_0, 0, pkts, pg_mask_firsts(NB_PKTS), &error); g_assert(!error); /* let the packet propagate and flow */ for (i = 0; i < 10; i++) { uint16_t count = 0; usleep(100000); pg_brick_poll(vhost_1, &count, &error); g_assert(!error); if (count) break; } result_pkts = pg_brick_east_burst_get(collect, &pkts_mask, &error); g_assert(!error); g_assert(result_pkts); g_assert(pg_brick_rx_bytes(vhost_0) == 0); g_assert(pg_brick_tx_bytes(vhost_0) != 0); g_assert(pg_brick_rx_bytes(vhost_1) != 0); g_assert(pg_brick_tx_bytes(vhost_1) == 0); /* kill QEMU */ pg_util_stop_qemu(qemu_pid, qemu_exit_signal); /* free result packets */ pg_packets_free(result_pkts, pkts_mask); /* free sent packet */ for (i = 0; i < NB_PKTS; i++) rte_pktmbuf_free(pkts[i]); /* break the graph */ pg_brick_unlink(collect, &error); g_assert(!error); /* clean up */ /* pg_brick_decref(vhost_0, &error); */ pg_brick_destroy(vhost_0); g_assert(!error); pg_brick_destroy(vhost_1); /* pg_brick_decref(vhost_1, &error); */ g_assert(!error); pg_brick_decref(collect, &error); g_assert(!error); /* stop vhost */ pg_vhost_stop(); }
int pg_bench_run(struct pg_bench *bench, struct pg_bench_stats *result, struct pg_error **error) { uint64_t bit; uint64_t it_mask; uint64_t i; uint16_t cnt; uint64_t pkts_burst; struct pg_brick_side *side = NULL; struct pg_brick *count_brick; struct pg_bench bl; if (bench == NULL || result == NULL || bench->pkts == NULL || bench->pkts_nb == 0 || bench->max_burst_cnt == 0 || bench->pkts_mask == 0) { *error = pg_error_new("missing or bad bench parameters"); return -1; } /* Link ouput brick to a nop brick to count outcoming packets. */ if (bench->count_brick == NULL) { count_brick = pg_nop_new("nop-bench", error); if (*error) return -1; if (bench->output_side == WEST_SIDE) pg_brick_link(count_brick, bench->output_brick, error); else pg_brick_link(bench->output_brick, count_brick, error); if (*error) return -1; } else { count_brick = bench->count_brick; } /* Set all stats to zero. */ memset(result, 0, sizeof(struct pg_bench_stats)); /* Setup callback to get burst count. */ pkts_burst = 0; switch (bench->input_brick->type) { case PG_MONOPOLE: side = bench->input_brick->sides; break; case PG_DIPOLE: case PG_MULTIPOLE: side = &(bench->input_brick->sides [pg_flip_side(bench->input_side)]); break; default: g_assert(0); break; } side->burst_count_cb = pg_bench_burst_cb; side->burst_count_private_data = (void *)(&pkts_burst); /* Compute average size of packets. */ it_mask = bench->pkts_mask; for (; it_mask;) { pg_low_bit_iterate_full(it_mask, bit, i); result->pkts_average_size += bench->pkts[i]->data_len; } result->pkts_average_size /= bench->pkts_nb; /* Let's run ! */ memcpy(&bl, bench, sizeof(struct pg_bench)); gettimeofday(&result->date_start, NULL); for (i = 0; i < bl.max_burst_cnt; i++) { /* Burst packets. */ pg_brick_burst(bl.input_brick, bl.input_side, 0, bl.pkts, bl.pkts_mask, error); sched_yield(); if (*error) return -1; /* Poll back packets if needed. */ if (bl.output_poll) pg_brick_poll(bl.output_brick, &cnt, error); if (bl.post_burst_op) bl.post_burst_op(bench); } gettimeofday(&result->date_end, NULL); memcpy(bench, &bl, sizeof(struct pg_bench)); result->pkts_sent = bench->max_burst_cnt * bench->pkts_nb; result->burst_cnt = bench->max_burst_cnt; result->pkts_burst = pkts_burst; result->pkts_received = pg_brick_pkts_count_get( count_brick, bench->output_side); if (bench->count_brick == NULL) { pg_brick_unlink(count_brick, error); if (*error) return -1; } return 0; }