161814702SLutz Donnerhacke /*-
261814702SLutz Donnerhacke * SPDX-License-Identifier: BSD-3-Clause
361814702SLutz Donnerhacke *
461814702SLutz Donnerhacke * Copyright 2021 Lutz Donnerhacke
561814702SLutz Donnerhacke *
661814702SLutz Donnerhacke * Redistribution and use in source and binary forms, with or without
761814702SLutz Donnerhacke * modification, are permitted provided that the following conditions
861814702SLutz Donnerhacke * are met:
961814702SLutz Donnerhacke *
1061814702SLutz Donnerhacke * 1. Redistributions of source code must retain the above copyright
1161814702SLutz Donnerhacke * notice, this list of conditions and the following disclaimer.
1261814702SLutz Donnerhacke * 2. Redistributions in binary form must reproduce the above
1361814702SLutz Donnerhacke * copyright notice, this list of conditions and the following
1461814702SLutz Donnerhacke * disclaimer in the documentation and/or other materials provided
1561814702SLutz Donnerhacke * with the distribution.
1661814702SLutz Donnerhacke * 3. Neither the name of the copyright holder nor the names of its
1761814702SLutz Donnerhacke * contributors may be used to endorse or promote products derived
1861814702SLutz Donnerhacke * from this software without specific prior written permission.
1961814702SLutz Donnerhacke *
2061814702SLutz Donnerhacke * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
2161814702SLutz Donnerhacke * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
2261814702SLutz Donnerhacke * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2361814702SLutz Donnerhacke * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2461814702SLutz Donnerhacke * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
2561814702SLutz Donnerhacke * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2661814702SLutz Donnerhacke * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2761814702SLutz Donnerhacke * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2861814702SLutz Donnerhacke * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
2961814702SLutz Donnerhacke * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
3061814702SLutz Donnerhacke * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
3161814702SLutz Donnerhacke * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3261814702SLutz Donnerhacke * SUCH DAMAGE.
3361814702SLutz Donnerhacke */
3461814702SLutz Donnerhacke #include <atf-c.h>
3561814702SLutz Donnerhacke #include <errno.h>
3661814702SLutz Donnerhacke #include <stdio.h>
3761814702SLutz Donnerhacke
3861814702SLutz Donnerhacke #include <net/ethernet.h>
3961814702SLutz Donnerhacke #include <netinet/in.h>
4061814702SLutz Donnerhacke #include <netinet/ip.h>
4161814702SLutz Donnerhacke #include <netinet/ip6.h>
4261814702SLutz Donnerhacke
4361814702SLutz Donnerhacke #include "util.h"
4461814702SLutz Donnerhacke #include <netgraph/ng_bridge.h>
4561814702SLutz Donnerhacke
4661814702SLutz Donnerhacke static void get_tablesize(char const *source, struct ng_mesg *msg, void *ctx);
4761814702SLutz Donnerhacke struct gettable
4861814702SLutz Donnerhacke {
4961814702SLutz Donnerhacke u_int32_t tok;
5061814702SLutz Donnerhacke int cnt;
5161814702SLutz Donnerhacke };
5261814702SLutz Donnerhacke
5361814702SLutz Donnerhacke struct frame4
5461814702SLutz Donnerhacke {
5561814702SLutz Donnerhacke struct ether_header eh;
5661814702SLutz Donnerhacke struct ip ip;
5761814702SLutz Donnerhacke char data[64];
5861814702SLutz Donnerhacke };
5961814702SLutz Donnerhacke struct frame6
6061814702SLutz Donnerhacke {
6161814702SLutz Donnerhacke struct ether_header eh;
6261814702SLutz Donnerhacke struct ip6_hdr ip;
6361814702SLutz Donnerhacke char data[64];
6461814702SLutz Donnerhacke };
6561814702SLutz Donnerhacke
6661814702SLutz Donnerhacke static struct frame4 msg4 = {
6761814702SLutz Donnerhacke .ip.ip_v = 4,
6861814702SLutz Donnerhacke .ip.ip_hl = 5,
6961814702SLutz Donnerhacke .ip.ip_ttl = 1,
7061814702SLutz Donnerhacke .ip.ip_p = 254,
7161814702SLutz Donnerhacke .ip.ip_src = {htonl(0x0a00dead)},
7261814702SLutz Donnerhacke .ip.ip_dst = {htonl(0x0a00beef)},
7361814702SLutz Donnerhacke .ip.ip_len = 32,
7461814702SLutz Donnerhacke .eh.ether_type = ETHERTYPE_IP,
7561814702SLutz Donnerhacke .eh.ether_shost = {2, 4, 6},
7661814702SLutz Donnerhacke .eh.ether_dhost = {2, 4, 6},
7761814702SLutz Donnerhacke };
7861814702SLutz Donnerhacke
7961814702SLutz Donnerhacke
8061814702SLutz Donnerhacke ATF_TC(basic);
ATF_TC_HEAD(basic,conf)8161814702SLutz Donnerhacke ATF_TC_HEAD(basic, conf)
8261814702SLutz Donnerhacke {
8361814702SLutz Donnerhacke atf_tc_set_md_var(conf, "require.user", "root");
8461814702SLutz Donnerhacke }
8561814702SLutz Donnerhacke
ATF_TC_BODY(basic,dummy)8661814702SLutz Donnerhacke ATF_TC_BODY(basic, dummy)
8761814702SLutz Donnerhacke {
88*5554abd9SLutz Donnerhacke ng_counter_t r;
8961814702SLutz Donnerhacke struct gettable rm;
9061814702SLutz Donnerhacke
9161814702SLutz Donnerhacke ng_init();
9261814702SLutz Donnerhacke ng_errors(PASS);
9361814702SLutz Donnerhacke ng_shutdown("bridge:");
9461814702SLutz Donnerhacke ng_errors(FAIL);
9561814702SLutz Donnerhacke
9661814702SLutz Donnerhacke ng_mkpeer(".", "a", "bridge", "link0");
9761814702SLutz Donnerhacke ng_name("a", "bridge");
9861814702SLutz Donnerhacke ng_connect(".", "b", "bridge:", "link1");
9961814702SLutz Donnerhacke ng_connect(".", "c", "bridge:", "link2");
10061814702SLutz Donnerhacke
10161814702SLutz Donnerhacke /* do not bounce back */
10261814702SLutz Donnerhacke ng_register_data("a", get_data0);
103*5554abd9SLutz Donnerhacke ng_counter_clear(r);
10461814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
10561814702SLutz Donnerhacke ng_send_data("a", &msg4, sizeof(msg4));
10661814702SLutz Donnerhacke ng_handle_events(50, &r);
10761814702SLutz Donnerhacke ATF_CHECK(r[0] == 0);
10861814702SLutz Donnerhacke
10961814702SLutz Donnerhacke /* send to others */
11061814702SLutz Donnerhacke ng_register_data("b", get_data1);
11161814702SLutz Donnerhacke ng_register_data("c", get_data2);
112*5554abd9SLutz Donnerhacke ng_counter_clear(r);
11361814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
11461814702SLutz Donnerhacke ng_send_data("a", &msg4, sizeof(msg4));
11561814702SLutz Donnerhacke ng_handle_events(50, &r);
11661814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1);
11761814702SLutz Donnerhacke
118*5554abd9SLutz Donnerhacke ng_counter_clear(r);
11961814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 2;
12061814702SLutz Donnerhacke ng_send_data("b", &msg4, sizeof(msg4));
12161814702SLutz Donnerhacke ng_handle_events(50, &r);
12261814702SLutz Donnerhacke ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1);
12361814702SLutz Donnerhacke
124*5554abd9SLutz Donnerhacke ng_counter_clear(r);
12561814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 3;
12661814702SLutz Donnerhacke ng_send_data("c", &msg4, sizeof(msg4));
12761814702SLutz Donnerhacke ng_handle_events(50, &r);
12861814702SLutz Donnerhacke ATF_CHECK(r[0] == 1 && r[1] == 1 && r[2] == 0);
12961814702SLutz Donnerhacke
13061814702SLutz Donnerhacke /* send to learned unicast */
131*5554abd9SLutz Donnerhacke ng_counter_clear(r);
13261814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
13361814702SLutz Donnerhacke msg4.eh.ether_dhost[5] = 3;
13461814702SLutz Donnerhacke ng_send_data("a", &msg4, sizeof(msg4));
13561814702SLutz Donnerhacke ng_handle_events(50, &r);
13661814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1);
13761814702SLutz Donnerhacke
13861814702SLutz Donnerhacke /* inspect mac table */
13961814702SLutz Donnerhacke ng_register_msg(get_tablesize);
14061814702SLutz Donnerhacke rm.tok = ng_send_msg("bridge:", "gettable");
14161814702SLutz Donnerhacke rm.cnt = 0;
14261814702SLutz Donnerhacke ng_handle_events(50, &rm);
14361814702SLutz Donnerhacke ATF_CHECK(rm.cnt == 3);
14461814702SLutz Donnerhacke
14561814702SLutz Donnerhacke /* remove a link */
14661814702SLutz Donnerhacke ng_rmhook(".", "b");
147*5554abd9SLutz Donnerhacke ng_counter_clear(r);
14861814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
14961814702SLutz Donnerhacke msg4.eh.ether_dhost[5] = 0;
15061814702SLutz Donnerhacke ng_send_data("a", &msg4, sizeof(msg4));
15161814702SLutz Donnerhacke ng_handle_events(50, &r);
15261814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1);
15361814702SLutz Donnerhacke
15461814702SLutz Donnerhacke /* inspect mac table */
15561814702SLutz Donnerhacke ng_register_msg(get_tablesize);
15661814702SLutz Donnerhacke rm.tok = ng_send_msg("bridge:", "gettable");
15761814702SLutz Donnerhacke rm.cnt = 0;
15861814702SLutz Donnerhacke ng_handle_events(50, &rm);
15961814702SLutz Donnerhacke ATF_CHECK(rm.cnt == 2);
16061814702SLutz Donnerhacke
16161814702SLutz Donnerhacke ng_shutdown("bridge:");
16261814702SLutz Donnerhacke }
16361814702SLutz Donnerhacke
16461814702SLutz Donnerhacke ATF_TC(persistence);
ATF_TC_HEAD(persistence,conf)16561814702SLutz Donnerhacke ATF_TC_HEAD(persistence, conf)
16661814702SLutz Donnerhacke {
16761814702SLutz Donnerhacke atf_tc_set_md_var(conf, "require.user", "root");
16861814702SLutz Donnerhacke }
16961814702SLutz Donnerhacke
ATF_TC_BODY(persistence,dummy)17061814702SLutz Donnerhacke ATF_TC_BODY(persistence, dummy)
17161814702SLutz Donnerhacke {
17261814702SLutz Donnerhacke ng_init();
17361814702SLutz Donnerhacke ng_errors(PASS);
17461814702SLutz Donnerhacke ng_shutdown("bridge:");
17561814702SLutz Donnerhacke ng_errors(FAIL);
17661814702SLutz Donnerhacke
17761814702SLutz Donnerhacke ng_mkpeer(".", "a", "bridge", "link0");
17861814702SLutz Donnerhacke ng_name("a", "bridge");
17961814702SLutz Donnerhacke
18061814702SLutz Donnerhacke ng_send_msg("bridge:", "setpersistent");
18161814702SLutz Donnerhacke ng_rmhook(".", "a");
18261814702SLutz Donnerhacke
18361814702SLutz Donnerhacke ng_shutdown("bridge:");
18461814702SLutz Donnerhacke }
18561814702SLutz Donnerhacke
18661814702SLutz Donnerhacke ATF_TC(loop);
ATF_TC_HEAD(loop,conf)18761814702SLutz Donnerhacke ATF_TC_HEAD(loop, conf)
18861814702SLutz Donnerhacke {
18961814702SLutz Donnerhacke atf_tc_set_md_var(conf, "require.user", "root");
19061814702SLutz Donnerhacke }
19161814702SLutz Donnerhacke
ATF_TC_BODY(loop,dummy)19261814702SLutz Donnerhacke ATF_TC_BODY(loop, dummy)
19361814702SLutz Donnerhacke {
194*5554abd9SLutz Donnerhacke ng_counter_t r;
195*5554abd9SLutz Donnerhacke int i;
19661814702SLutz Donnerhacke
19761814702SLutz Donnerhacke ng_init();
19861814702SLutz Donnerhacke ng_errors(PASS);
19961814702SLutz Donnerhacke ng_shutdown("bridge1:");
20061814702SLutz Donnerhacke ng_shutdown("bridge2:");
20161814702SLutz Donnerhacke ng_errors(FAIL);
20261814702SLutz Donnerhacke
20361814702SLutz Donnerhacke ng_mkpeer(".", "a", "bridge", "link0");
20461814702SLutz Donnerhacke ng_name("a", "bridge1");
20561814702SLutz Donnerhacke ng_mkpeer(".", "b", "bridge", "link1");
20661814702SLutz Donnerhacke ng_name("b", "bridge2");
20761814702SLutz Donnerhacke
20861814702SLutz Donnerhacke ng_register_data("a", get_data0);
20961814702SLutz Donnerhacke ng_register_data("b", get_data1);
21061814702SLutz Donnerhacke
21161814702SLutz Donnerhacke /*-
21261814702SLutz Donnerhacke * Open loop
21361814702SLutz Donnerhacke *
21461814702SLutz Donnerhacke * /-- bridge1
21561814702SLutz Donnerhacke * . < |
21661814702SLutz Donnerhacke * \-- bridge2
21761814702SLutz Donnerhacke */
21861814702SLutz Donnerhacke ng_connect("bridge1:", "link11", "bridge2:", "link11");
21961814702SLutz Donnerhacke
220*5554abd9SLutz Donnerhacke ng_counter_clear(r);
22161814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
22261814702SLutz Donnerhacke ng_send_data("a", &msg4, sizeof(msg4));
22361814702SLutz Donnerhacke ng_handle_events(50, &r);
22461814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 1);
22561814702SLutz Donnerhacke
22661814702SLutz Donnerhacke /*-
22761814702SLutz Donnerhacke * Closed loop, DANGEROUS!
22861814702SLutz Donnerhacke *
22961814702SLutz Donnerhacke * /-- bridge1 -\
23061814702SLutz Donnerhacke * . < | |
23161814702SLutz Donnerhacke * \-- bridge2 -/
23261814702SLutz Donnerhacke */
23361814702SLutz Donnerhacke ng_connect("bridge1:", "link12", "bridge2:", "link12");
23461814702SLutz Donnerhacke
235*5554abd9SLutz Donnerhacke ng_counter_clear(r);
23661814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
23761814702SLutz Donnerhacke ng_errors(PASS);
23861814702SLutz Donnerhacke ng_send_data("a", &msg4, sizeof(msg4));
23961814702SLutz Donnerhacke ATF_CHECK_ERRNO(ELOOP, errno != 0); /* loop might be detected */
24061814702SLutz Donnerhacke ng_errors(FAIL);
24161814702SLutz Donnerhacke for (i = 0; i < 10; i++) /* don't run forever */
24261814702SLutz Donnerhacke if (!ng_handle_event(50, &r))
24361814702SLutz Donnerhacke break;
24461814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 1);
24561814702SLutz Donnerhacke
24661814702SLutz Donnerhacke ng_shutdown("bridge1:");
24761814702SLutz Donnerhacke ng_shutdown("bridge2:");
24861814702SLutz Donnerhacke }
24961814702SLutz Donnerhacke
25061814702SLutz Donnerhacke ATF_TC(many_unicasts);
ATF_TC_HEAD(many_unicasts,conf)25161814702SLutz Donnerhacke ATF_TC_HEAD(many_unicasts, conf)
25261814702SLutz Donnerhacke {
25361814702SLutz Donnerhacke atf_tc_set_md_var(conf, "require.user", "root");
25461814702SLutz Donnerhacke }
25561814702SLutz Donnerhacke
ATF_TC_BODY(many_unicasts,dummy)25661814702SLutz Donnerhacke ATF_TC_BODY(many_unicasts, dummy)
25761814702SLutz Donnerhacke {
258*5554abd9SLutz Donnerhacke ng_counter_t r;
259*5554abd9SLutz Donnerhacke int i;
26061814702SLutz Donnerhacke const int HOOKS = 1000;
26161814702SLutz Donnerhacke struct gettable rm;
26261814702SLutz Donnerhacke
26361814702SLutz Donnerhacke ng_init();
26461814702SLutz Donnerhacke ng_errors(PASS);
26561814702SLutz Donnerhacke ng_shutdown("bridge:");
26661814702SLutz Donnerhacke ng_errors(FAIL);
26761814702SLutz Donnerhacke
26861814702SLutz Donnerhacke ng_mkpeer(".", "a", "bridge", "link0");
26961814702SLutz Donnerhacke ng_name("a", "bridge");
27061814702SLutz Donnerhacke ng_register_data("a", get_data0);
27161814702SLutz Donnerhacke
27261814702SLutz Donnerhacke /* learn MAC */
273*5554abd9SLutz Donnerhacke ng_counter_clear(r);
27461814702SLutz Donnerhacke msg4.eh.ether_shost[3] = 0xff;
27561814702SLutz Donnerhacke ng_send_data("a", &msg4, sizeof(msg4));
27661814702SLutz Donnerhacke ng_handle_events(50, &r);
27761814702SLutz Donnerhacke ATF_CHECK(r[0] == 0);
27861814702SLutz Donnerhacke
27961814702SLutz Donnerhacke /* use learned MAC as destination */
28061814702SLutz Donnerhacke msg4.eh.ether_shost[3] = 0;
28161814702SLutz Donnerhacke msg4.eh.ether_dhost[3] = 0xff;
28261814702SLutz Donnerhacke
28361814702SLutz Donnerhacke /* now send */
284*5554abd9SLutz Donnerhacke ng_counter_clear(r);
28561814702SLutz Donnerhacke for (i = 1; i <= HOOKS; i++)
28661814702SLutz Donnerhacke {
28761814702SLutz Donnerhacke char hook[20];
28861814702SLutz Donnerhacke
28961814702SLutz Donnerhacke snprintf(hook, sizeof(hook), "link%d", i);
29061814702SLutz Donnerhacke ng_connect(".", hook, "bridge:", hook);
29161814702SLutz Donnerhacke ng_register_data(hook, get_data2);
29261814702SLutz Donnerhacke
29361814702SLutz Donnerhacke msg4.eh.ether_shost[4] = i >> 8;
29461814702SLutz Donnerhacke msg4.eh.ether_shost[5] = i & 0xff;
29561814702SLutz Donnerhacke ng_errors(PASS);
29661814702SLutz Donnerhacke ng_send_data(hook, &msg4, sizeof(msg4));
29761814702SLutz Donnerhacke ng_errors(FAIL);
29861814702SLutz Donnerhacke if (errno != 0)
29961814702SLutz Donnerhacke break;
30061814702SLutz Donnerhacke ng_handle_events(50, &r);
30161814702SLutz Donnerhacke }
30261814702SLutz Donnerhacke ATF_CHECK(r[0] == HOOKS && r[2] == 0);
30361814702SLutz Donnerhacke
30461814702SLutz Donnerhacke /* inspect mac table */
30561814702SLutz Donnerhacke ng_register_msg(get_tablesize);
30661814702SLutz Donnerhacke rm.cnt = 0;
30761814702SLutz Donnerhacke ng_errors(PASS);
30861814702SLutz Donnerhacke rm.tok = ng_send_msg("bridge:", "gettable");
30961814702SLutz Donnerhacke ng_errors(FAIL);
31061814702SLutz Donnerhacke if (rm.tok == (u_int32_t)-1)
31161814702SLutz Donnerhacke {
31261814702SLutz Donnerhacke ATF_CHECK_ERRNO(ENOBUFS, 1);
31361814702SLutz Donnerhacke atf_tc_expect_fail("response too large");
31461814702SLutz Donnerhacke }
31561814702SLutz Donnerhacke ng_handle_events(50, &rm);
31661814702SLutz Donnerhacke ATF_CHECK(rm.cnt == HOOKS + 1);
31761814702SLutz Donnerhacke atf_tc_expect_pass();
31861814702SLutz Donnerhacke
31961814702SLutz Donnerhacke ng_shutdown("bridge:");
32061814702SLutz Donnerhacke }
32161814702SLutz Donnerhacke
32261814702SLutz Donnerhacke ATF_TC(many_broadcasts);
ATF_TC_HEAD(many_broadcasts,conf)32361814702SLutz Donnerhacke ATF_TC_HEAD(many_broadcasts, conf)
32461814702SLutz Donnerhacke {
32561814702SLutz Donnerhacke atf_tc_set_md_var(conf, "require.user", "root");
32661814702SLutz Donnerhacke }
32761814702SLutz Donnerhacke
ATF_TC_BODY(many_broadcasts,dummy)32861814702SLutz Donnerhacke ATF_TC_BODY(many_broadcasts, dummy)
32961814702SLutz Donnerhacke {
330*5554abd9SLutz Donnerhacke ng_counter_t r;
331*5554abd9SLutz Donnerhacke int i;
33261814702SLutz Donnerhacke const int HOOKS = 1000;
33361814702SLutz Donnerhacke
33461814702SLutz Donnerhacke ng_init();
33561814702SLutz Donnerhacke ng_errors(PASS);
33661814702SLutz Donnerhacke ng_shutdown("bridge:");
33761814702SLutz Donnerhacke ng_errors(FAIL);
33861814702SLutz Donnerhacke
33961814702SLutz Donnerhacke ng_mkpeer(".", "a", "bridge", "link0");
34061814702SLutz Donnerhacke ng_name("a", "bridge");
34161814702SLutz Donnerhacke ng_register_data("a", get_data0);
34261814702SLutz Donnerhacke
34361814702SLutz Donnerhacke /* learn MAC */
344*5554abd9SLutz Donnerhacke ng_counter_clear(r);
34561814702SLutz Donnerhacke msg4.eh.ether_shost[3] = 0xff;
34661814702SLutz Donnerhacke ng_send_data("a", &msg4, sizeof(msg4));
34761814702SLutz Donnerhacke ng_handle_events(50, &r);
34861814702SLutz Donnerhacke ATF_CHECK(r[0] == 0);
34961814702SLutz Donnerhacke
35061814702SLutz Donnerhacke /* use broadcast MAC */
35161814702SLutz Donnerhacke msg4.eh.ether_shost[3] = 0;
35261814702SLutz Donnerhacke memset(msg4.eh.ether_dhost, 0xff, sizeof(msg4.eh.ether_dhost));
35361814702SLutz Donnerhacke
35461814702SLutz Donnerhacke /* now send */
355*5554abd9SLutz Donnerhacke ng_counter_clear(r);
35661814702SLutz Donnerhacke for (i = 1; i <= HOOKS; i++)
35761814702SLutz Donnerhacke {
35861814702SLutz Donnerhacke char hook[20];
35961814702SLutz Donnerhacke
36061814702SLutz Donnerhacke snprintf(hook, sizeof(hook), "link%d", i);
36161814702SLutz Donnerhacke ng_connect(".", hook, "bridge:", hook);
36261814702SLutz Donnerhacke ng_register_data(hook, get_data3);
36361814702SLutz Donnerhacke
36461814702SLutz Donnerhacke msg4.eh.ether_shost[4] = i >> 8;
36561814702SLutz Donnerhacke msg4.eh.ether_shost[5] = i & 0xff;
36661814702SLutz Donnerhacke ng_errors(PASS);
36761814702SLutz Donnerhacke ng_send_data(hook, &msg4, sizeof(msg4));
36861814702SLutz Donnerhacke ng_errors(FAIL);
36961814702SLutz Donnerhacke if (errno != 0)
37061814702SLutz Donnerhacke break;
37161814702SLutz Donnerhacke ng_handle_events(50, &r);
37261814702SLutz Donnerhacke }
37361814702SLutz Donnerhacke ATF_CHECK(r[0] > 100 && r[3] > 100);
37461814702SLutz Donnerhacke if (i < HOOKS)
37561814702SLutz Donnerhacke atf_tc_expect_fail("netgraph queue full (%d)", i);
37661814702SLutz Donnerhacke ATF_CHECK(r[0] == HOOKS);
37761814702SLutz Donnerhacke atf_tc_expect_pass();
37861814702SLutz Donnerhacke
37961814702SLutz Donnerhacke ng_shutdown("bridge:");
38061814702SLutz Donnerhacke }
38161814702SLutz Donnerhacke
38261814702SLutz Donnerhacke ATF_TC(uplink_private);
ATF_TC_HEAD(uplink_private,conf)38361814702SLutz Donnerhacke ATF_TC_HEAD(uplink_private, conf)
38461814702SLutz Donnerhacke {
38561814702SLutz Donnerhacke atf_tc_set_md_var(conf, "require.user", "root");
38661814702SLutz Donnerhacke }
38761814702SLutz Donnerhacke
ATF_TC_BODY(uplink_private,dummy)38861814702SLutz Donnerhacke ATF_TC_BODY(uplink_private, dummy)
38961814702SLutz Donnerhacke {
390*5554abd9SLutz Donnerhacke ng_counter_t r;
39161814702SLutz Donnerhacke struct gettable rm;
39261814702SLutz Donnerhacke
39361814702SLutz Donnerhacke ng_init();
39461814702SLutz Donnerhacke ng_errors(PASS);
39561814702SLutz Donnerhacke ng_shutdown("bridge:");
39661814702SLutz Donnerhacke
39761814702SLutz Donnerhacke ng_mkpeer(".", "u1", "bridge", "uplink1");
39861814702SLutz Donnerhacke if (errno > 0)
39961814702SLutz Donnerhacke atf_tc_skip("uplinks are not supported.");
40061814702SLutz Donnerhacke ng_errors(FAIL);
40161814702SLutz Donnerhacke ng_name("u1", "bridge");
40261814702SLutz Donnerhacke ng_register_data("u1", get_data1);
40361814702SLutz Donnerhacke ng_connect(".", "u2", "bridge:", "uplink2");
40461814702SLutz Donnerhacke ng_register_data("u2", get_data2);
40561814702SLutz Donnerhacke ng_connect(".", "l0", "bridge:", "link0");
40661814702SLutz Donnerhacke ng_register_data("l0", get_data0);
40761814702SLutz Donnerhacke ng_connect(".", "l3", "bridge:", "link3");
40861814702SLutz Donnerhacke ng_register_data("l3", get_data3);
40961814702SLutz Donnerhacke
41061814702SLutz Donnerhacke /* unknown unicast 0 from uplink1 */
411*5554abd9SLutz Donnerhacke ng_counter_clear(r);
41261814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
41361814702SLutz Donnerhacke ng_send_data("u1", &msg4, sizeof(msg4));
41461814702SLutz Donnerhacke ng_handle_events(50, &r);
41561814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1 && r[3] == 0);
41661814702SLutz Donnerhacke
41761814702SLutz Donnerhacke /* unknown unicast 2 from link0 */
418*5554abd9SLutz Donnerhacke ng_counter_clear(r);
41961814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 0;
42061814702SLutz Donnerhacke msg4.eh.ether_dhost[5] = 2;
42161814702SLutz Donnerhacke ng_send_data("l0", &msg4, sizeof(msg4));
42261814702SLutz Donnerhacke ng_handle_events(50, &r);
42361814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 0);
42461814702SLutz Donnerhacke
42561814702SLutz Donnerhacke /* known unicast 0 from uplink2 */
426*5554abd9SLutz Donnerhacke ng_counter_clear(r);
42761814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 2;
42861814702SLutz Donnerhacke msg4.eh.ether_dhost[5] = 0;
42961814702SLutz Donnerhacke ng_send_data("u2", &msg4, sizeof(msg4));
43061814702SLutz Donnerhacke ng_handle_events(50, &r);
43161814702SLutz Donnerhacke ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0);
43261814702SLutz Donnerhacke
43361814702SLutz Donnerhacke /* known unicast 0 from link3 */
434*5554abd9SLutz Donnerhacke ng_counter_clear(r);
43561814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 3;
43661814702SLutz Donnerhacke msg4.eh.ether_dhost[5] = 0;
43761814702SLutz Donnerhacke ng_send_data("l3", &msg4, sizeof(msg4));
43861814702SLutz Donnerhacke ng_handle_events(50, &r);
43961814702SLutz Donnerhacke ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0);
44061814702SLutz Donnerhacke
44161814702SLutz Donnerhacke /* (un)known unicast 2 from uplink1 */
442*5554abd9SLutz Donnerhacke ng_counter_clear(r);
44361814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
44461814702SLutz Donnerhacke msg4.eh.ether_dhost[5] = 2;
44561814702SLutz Donnerhacke ng_send_data("u1", &msg4, sizeof(msg4));
44661814702SLutz Donnerhacke ng_handle_events(50, &r);
44761814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1 && r[3] == 0);
44861814702SLutz Donnerhacke
44961814702SLutz Donnerhacke /* (un)known unicast 2 from link0 */
450*5554abd9SLutz Donnerhacke ng_counter_clear(r);
45161814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 0;
45261814702SLutz Donnerhacke ng_send_data("l0", &msg4, sizeof(msg4));
45361814702SLutz Donnerhacke ng_handle_events(50, &r);
45461814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 0);
45561814702SLutz Donnerhacke
45661814702SLutz Donnerhacke /* unknown multicast 2 from uplink1 */
457*5554abd9SLutz Donnerhacke ng_counter_clear(r);
45861814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
45961814702SLutz Donnerhacke msg4.eh.ether_dhost[0] = 0xff;
46061814702SLutz Donnerhacke ng_send_data("u1", &msg4, sizeof(msg4));
46161814702SLutz Donnerhacke ng_handle_events(50, &r);
46261814702SLutz Donnerhacke ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1);
46361814702SLutz Donnerhacke
46461814702SLutz Donnerhacke /* unknown multicast 2 from link0 */
465*5554abd9SLutz Donnerhacke ng_counter_clear(r);
46661814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 0;
46761814702SLutz Donnerhacke ng_send_data("l0", &msg4, sizeof(msg4));
46861814702SLutz Donnerhacke ng_handle_events(50, &r);
46961814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1);
47061814702SLutz Donnerhacke
47161814702SLutz Donnerhacke /* broadcast from uplink1 */
472*5554abd9SLutz Donnerhacke ng_counter_clear(r);
47361814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
47461814702SLutz Donnerhacke memset(msg4.eh.ether_dhost, 0xff, sizeof(msg4.eh.ether_dhost));
47561814702SLutz Donnerhacke ng_send_data("u1", &msg4, sizeof(msg4));
47661814702SLutz Donnerhacke ng_handle_events(50, &r);
47761814702SLutz Donnerhacke ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1);
47861814702SLutz Donnerhacke
47961814702SLutz Donnerhacke /* broadcast from link0 */
480*5554abd9SLutz Donnerhacke ng_counter_clear(r);
48161814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 0;
48261814702SLutz Donnerhacke ng_send_data("l0", &msg4, sizeof(msg4));
48361814702SLutz Donnerhacke ng_handle_events(50, &r);
48461814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1);
48561814702SLutz Donnerhacke
48661814702SLutz Donnerhacke /* inspect mac table */
48761814702SLutz Donnerhacke ng_register_msg(get_tablesize);
48861814702SLutz Donnerhacke rm.tok = ng_send_msg("bridge:", "gettable");
48961814702SLutz Donnerhacke rm.cnt = 0;
49061814702SLutz Donnerhacke ng_handle_events(50, &rm);
49161814702SLutz Donnerhacke ATF_CHECK(rm.cnt == 2);
49261814702SLutz Donnerhacke
49361814702SLutz Donnerhacke ng_shutdown("bridge:");
49461814702SLutz Donnerhacke }
49561814702SLutz Donnerhacke
49661814702SLutz Donnerhacke ATF_TC(uplink_classic);
ATF_TC_HEAD(uplink_classic,conf)49761814702SLutz Donnerhacke ATF_TC_HEAD(uplink_classic, conf)
49861814702SLutz Donnerhacke {
49961814702SLutz Donnerhacke atf_tc_set_md_var(conf, "require.user", "root");
50061814702SLutz Donnerhacke }
50161814702SLutz Donnerhacke
ATF_TC_BODY(uplink_classic,dummy)50261814702SLutz Donnerhacke ATF_TC_BODY(uplink_classic, dummy)
50361814702SLutz Donnerhacke {
504*5554abd9SLutz Donnerhacke ng_counter_t r;
50561814702SLutz Donnerhacke struct gettable rm;
50661814702SLutz Donnerhacke
50761814702SLutz Donnerhacke ng_init();
50861814702SLutz Donnerhacke ng_errors(PASS);
50961814702SLutz Donnerhacke ng_shutdown("bridge:");
51061814702SLutz Donnerhacke
51161814702SLutz Donnerhacke ng_mkpeer(".", "l0", "bridge", "link0");
51261814702SLutz Donnerhacke if (errno > 0)
51361814702SLutz Donnerhacke atf_tc_skip("uplinks are not supported.");
51461814702SLutz Donnerhacke ng_errors(FAIL);
51561814702SLutz Donnerhacke ng_name("l0", "bridge");
51661814702SLutz Donnerhacke ng_register_data("l0", get_data0);
51761814702SLutz Donnerhacke ng_connect(".", "u1", "bridge:", "uplink1");
51861814702SLutz Donnerhacke ng_register_data("u1", get_data1);
51961814702SLutz Donnerhacke ng_connect(".", "u2", "bridge:", "uplink2");
52061814702SLutz Donnerhacke ng_register_data("u2", get_data2);
52161814702SLutz Donnerhacke ng_connect(".", "l3", "bridge:", "link3");
52261814702SLutz Donnerhacke ng_register_data("l3", get_data3);
52361814702SLutz Donnerhacke
52461814702SLutz Donnerhacke /* unknown unicast 0 from uplink1 */
525*5554abd9SLutz Donnerhacke ng_counter_clear(r);
52661814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
52761814702SLutz Donnerhacke ng_send_data("u1", &msg4, sizeof(msg4));
52861814702SLutz Donnerhacke ng_handle_events(50, &r);
52961814702SLutz Donnerhacke ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1);
53061814702SLutz Donnerhacke
53161814702SLutz Donnerhacke /* unknown unicast 2 from link0 */
532*5554abd9SLutz Donnerhacke ng_counter_clear(r);
53361814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 0;
53461814702SLutz Donnerhacke msg4.eh.ether_dhost[5] = 2;
53561814702SLutz Donnerhacke ng_send_data("l0", &msg4, sizeof(msg4));
53661814702SLutz Donnerhacke ng_handle_events(50, &r);
53761814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1);
53861814702SLutz Donnerhacke
53961814702SLutz Donnerhacke /* known unicast 0 from uplink2 */
540*5554abd9SLutz Donnerhacke ng_counter_clear(r);
54161814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 2;
54261814702SLutz Donnerhacke msg4.eh.ether_dhost[5] = 0;
54361814702SLutz Donnerhacke ng_send_data("u2", &msg4, sizeof(msg4));
54461814702SLutz Donnerhacke ng_handle_events(50, &r);
54561814702SLutz Donnerhacke ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0);
54661814702SLutz Donnerhacke
54761814702SLutz Donnerhacke /* known unicast 0 from link3 */
548*5554abd9SLutz Donnerhacke ng_counter_clear(r);
54961814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 3;
55061814702SLutz Donnerhacke msg4.eh.ether_dhost[5] = 0;
55161814702SLutz Donnerhacke ng_send_data("l3", &msg4, sizeof(msg4));
55261814702SLutz Donnerhacke ng_handle_events(50, &r);
55361814702SLutz Donnerhacke ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0);
55461814702SLutz Donnerhacke
55561814702SLutz Donnerhacke /* (un)known unicast 2 from uplink1 */
556*5554abd9SLutz Donnerhacke ng_counter_clear(r);
55761814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
55861814702SLutz Donnerhacke msg4.eh.ether_dhost[5] = 2;
55961814702SLutz Donnerhacke ng_send_data("u1", &msg4, sizeof(msg4));
56061814702SLutz Donnerhacke ng_handle_events(50, &r);
56161814702SLutz Donnerhacke ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1);
56261814702SLutz Donnerhacke
56361814702SLutz Donnerhacke /* (un)known unicast 2 from link0 */
564*5554abd9SLutz Donnerhacke ng_counter_clear(r);
56561814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 0;
56661814702SLutz Donnerhacke ng_send_data("l0", &msg4, sizeof(msg4));
56761814702SLutz Donnerhacke ng_handle_events(50, &r);
56861814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1);
56961814702SLutz Donnerhacke
57061814702SLutz Donnerhacke /* unknown multicast 2 from uplink1 */
571*5554abd9SLutz Donnerhacke ng_counter_clear(r);
57261814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
57361814702SLutz Donnerhacke msg4.eh.ether_dhost[0] = 0xff;
57461814702SLutz Donnerhacke ng_send_data("u1", &msg4, sizeof(msg4));
57561814702SLutz Donnerhacke ng_handle_events(50, &r);
57661814702SLutz Donnerhacke ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1);
57761814702SLutz Donnerhacke
57861814702SLutz Donnerhacke /* unknown multicast 2 from link0 */
579*5554abd9SLutz Donnerhacke ng_counter_clear(r);
58061814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 0;
58161814702SLutz Donnerhacke ng_send_data("l0", &msg4, sizeof(msg4));
58261814702SLutz Donnerhacke ng_handle_events(50, &r);
58361814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1);
58461814702SLutz Donnerhacke
58561814702SLutz Donnerhacke /* broadcast from uplink1 */
586*5554abd9SLutz Donnerhacke ng_counter_clear(r);
58761814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 1;
58861814702SLutz Donnerhacke memset(msg4.eh.ether_dhost, 0xff, sizeof(msg4.eh.ether_dhost));
58961814702SLutz Donnerhacke ng_send_data("u1", &msg4, sizeof(msg4));
59061814702SLutz Donnerhacke ng_handle_events(50, &r);
59161814702SLutz Donnerhacke ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1);
59261814702SLutz Donnerhacke
59361814702SLutz Donnerhacke /* broadcast from link0 */
594*5554abd9SLutz Donnerhacke ng_counter_clear(r);
59561814702SLutz Donnerhacke msg4.eh.ether_shost[5] = 0;
59661814702SLutz Donnerhacke ng_send_data("l0", &msg4, sizeof(msg4));
59761814702SLutz Donnerhacke ng_handle_events(50, &r);
59861814702SLutz Donnerhacke ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1);
59961814702SLutz Donnerhacke
60061814702SLutz Donnerhacke /* inspect mac table */
60161814702SLutz Donnerhacke ng_register_msg(get_tablesize);
60261814702SLutz Donnerhacke rm.tok = ng_send_msg("bridge:", "gettable");
60361814702SLutz Donnerhacke rm.cnt = 0;
60461814702SLutz Donnerhacke ng_handle_events(50, &rm);
60561814702SLutz Donnerhacke ATF_CHECK(rm.cnt == 2);
60661814702SLutz Donnerhacke
60761814702SLutz Donnerhacke ng_shutdown("bridge:");
60861814702SLutz Donnerhacke }
60961814702SLutz Donnerhacke
ATF_TP_ADD_TCS(bridge)61061814702SLutz Donnerhacke ATF_TP_ADD_TCS(bridge)
61161814702SLutz Donnerhacke {
61261814702SLutz Donnerhacke ATF_TP_ADD_TC(bridge, basic);
61361814702SLutz Donnerhacke ATF_TP_ADD_TC(bridge, loop);
61461814702SLutz Donnerhacke ATF_TP_ADD_TC(bridge, persistence);
61561814702SLutz Donnerhacke ATF_TP_ADD_TC(bridge, many_unicasts);
61661814702SLutz Donnerhacke ATF_TP_ADD_TC(bridge, many_broadcasts);
61761814702SLutz Donnerhacke ATF_TP_ADD_TC(bridge, uplink_private);
61861814702SLutz Donnerhacke ATF_TP_ADD_TC(bridge, uplink_classic);
61961814702SLutz Donnerhacke
62061814702SLutz Donnerhacke return atf_no_error();
62161814702SLutz Donnerhacke }
62261814702SLutz Donnerhacke
62361814702SLutz Donnerhacke static void
get_tablesize(char const * source,struct ng_mesg * msg,void * ctx)62461814702SLutz Donnerhacke get_tablesize(char const *source, struct ng_mesg *msg, void *ctx)
62561814702SLutz Donnerhacke {
62661814702SLutz Donnerhacke struct gettable *rm = ctx;
62761814702SLutz Donnerhacke struct ng_bridge_host_ary *gt = (void *)msg->data;
62861814702SLutz Donnerhacke
62961814702SLutz Donnerhacke fprintf(stderr, "Response from %s to query %d\n", source, msg->header.token);
63061814702SLutz Donnerhacke if (rm->tok == msg->header.token)
63161814702SLutz Donnerhacke rm->cnt = gt->numHosts;
63261814702SLutz Donnerhacke }
633