1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright 2021 Lutz Donnerhacke 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following 14 * disclaimer in the documentation and/or other materials provided 15 * with the distribution. 16 * 3. Neither the name of the copyright holder nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 21 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 27 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 29 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 30 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 31 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 #include <atf-c.h> 35 #include <errno.h> 36 #include <stdio.h> 37 38 #include <net/ethernet.h> 39 #include <netinet/in.h> 40 #include <netinet/ip.h> 41 #include <netinet/ip6.h> 42 43 #include "util.h" 44 #include <netgraph/ng_bridge.h> 45 46 static void get_data0(void *data, size_t len, void *ctx); 47 static void get_data1(void *data, size_t len, void *ctx); 48 static void get_data2(void *data, size_t len, void *ctx); 49 static void get_data3(void *data, size_t len, void *ctx); 50 51 static void get_tablesize(char const *source, struct ng_mesg *msg, void *ctx); 52 struct gettable 53 { 54 u_int32_t tok; 55 int cnt; 56 }; 57 58 struct frame4 59 { 60 struct ether_header eh; 61 struct ip ip; 62 char data[64]; 63 }; 64 struct frame6 65 { 66 struct ether_header eh; 67 struct ip6_hdr ip; 68 char data[64]; 69 }; 70 71 static struct frame4 msg4 = { 72 .ip.ip_v = 4, 73 .ip.ip_hl = 5, 74 .ip.ip_ttl = 1, 75 .ip.ip_p = 254, 76 .ip.ip_src = {htonl(0x0a00dead)}, 77 .ip.ip_dst = {htonl(0x0a00beef)}, 78 .ip.ip_len = 32, 79 .eh.ether_type = ETHERTYPE_IP, 80 .eh.ether_shost = {2, 4, 6}, 81 .eh.ether_dhost = {2, 4, 6}, 82 }; 83 84 85 ATF_TC(basic); 86 ATF_TC_HEAD(basic, conf) 87 { 88 atf_tc_set_md_var(conf, "require.user", "root"); 89 } 90 91 ATF_TC_BODY(basic, dummy) 92 { 93 int r[4]; 94 struct gettable rm; 95 96 ng_init(); 97 ng_errors(PASS); 98 ng_shutdown("bridge:"); 99 ng_errors(FAIL); 100 101 ng_mkpeer(".", "a", "bridge", "link0"); 102 ng_name("a", "bridge"); 103 ng_connect(".", "b", "bridge:", "link1"); 104 ng_connect(".", "c", "bridge:", "link2"); 105 106 /* do not bounce back */ 107 ng_register_data("a", get_data0); 108 bzero(r, sizeof(r)); 109 msg4.eh.ether_shost[5] = 1; 110 ng_send_data("a", &msg4, sizeof(msg4)); 111 ng_handle_events(50, &r); 112 ATF_CHECK(r[0] == 0); 113 114 /* send to others */ 115 ng_register_data("b", get_data1); 116 ng_register_data("c", get_data2); 117 bzero(r, sizeof(r)); 118 msg4.eh.ether_shost[5] = 1; 119 ng_send_data("a", &msg4, sizeof(msg4)); 120 ng_handle_events(50, &r); 121 ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1); 122 123 bzero(r, sizeof(r)); 124 msg4.eh.ether_shost[5] = 2; 125 ng_send_data("b", &msg4, sizeof(msg4)); 126 ng_handle_events(50, &r); 127 ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1); 128 129 bzero(r, sizeof(r)); 130 msg4.eh.ether_shost[5] = 3; 131 ng_send_data("c", &msg4, sizeof(msg4)); 132 ng_handle_events(50, &r); 133 ATF_CHECK(r[0] == 1 && r[1] == 1 && r[2] == 0); 134 135 /* send to learned unicast */ 136 bzero(r, sizeof(r)); 137 msg4.eh.ether_shost[5] = 1; 138 msg4.eh.ether_dhost[5] = 3; 139 ng_send_data("a", &msg4, sizeof(msg4)); 140 ng_handle_events(50, &r); 141 ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1); 142 143 /* inspect mac table */ 144 ng_register_msg(get_tablesize); 145 rm.tok = ng_send_msg("bridge:", "gettable"); 146 rm.cnt = 0; 147 ng_handle_events(50, &rm); 148 ATF_CHECK(rm.cnt == 3); 149 150 /* remove a link */ 151 ng_rmhook(".", "b"); 152 bzero(r, sizeof(r)); 153 msg4.eh.ether_shost[5] = 1; 154 msg4.eh.ether_dhost[5] = 0; 155 ng_send_data("a", &msg4, sizeof(msg4)); 156 ng_handle_events(50, &r); 157 ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1); 158 159 /* inspect mac table */ 160 ng_register_msg(get_tablesize); 161 rm.tok = ng_send_msg("bridge:", "gettable"); 162 rm.cnt = 0; 163 ng_handle_events(50, &rm); 164 ATF_CHECK(rm.cnt == 2); 165 166 ng_shutdown("bridge:"); 167 } 168 169 ATF_TC(persistence); 170 ATF_TC_HEAD(persistence, conf) 171 { 172 atf_tc_set_md_var(conf, "require.user", "root"); 173 } 174 175 ATF_TC_BODY(persistence, dummy) 176 { 177 ng_init(); 178 ng_errors(PASS); 179 ng_shutdown("bridge:"); 180 ng_errors(FAIL); 181 182 ng_mkpeer(".", "a", "bridge", "link0"); 183 ng_name("a", "bridge"); 184 185 ng_send_msg("bridge:", "setpersistent"); 186 ng_rmhook(".", "a"); 187 188 ng_shutdown("bridge:"); 189 } 190 191 ATF_TC(loop); 192 ATF_TC_HEAD(loop, conf) 193 { 194 atf_tc_set_md_var(conf, "require.user", "root"); 195 } 196 197 ATF_TC_BODY(loop, dummy) 198 { 199 int r[4], i; 200 201 ng_init(); 202 ng_errors(PASS); 203 ng_shutdown("bridge1:"); 204 ng_shutdown("bridge2:"); 205 ng_errors(FAIL); 206 207 ng_mkpeer(".", "a", "bridge", "link0"); 208 ng_name("a", "bridge1"); 209 ng_mkpeer(".", "b", "bridge", "link1"); 210 ng_name("b", "bridge2"); 211 212 ng_register_data("a", get_data0); 213 ng_register_data("b", get_data1); 214 215 /*- 216 * Open loop 217 * 218 * /-- bridge1 219 * . < | 220 * \-- bridge2 221 */ 222 ng_connect("bridge1:", "link11", "bridge2:", "link11"); 223 224 bzero(r, sizeof(r)); 225 msg4.eh.ether_shost[5] = 1; 226 ng_send_data("a", &msg4, sizeof(msg4)); 227 ng_handle_events(50, &r); 228 ATF_CHECK(r[0] == 0 && r[1] == 1); 229 230 /*- 231 * Closed loop, DANGEROUS! 232 * 233 * /-- bridge1 -\ 234 * . < | | 235 * \-- bridge2 -/ 236 */ 237 ng_connect("bridge1:", "link12", "bridge2:", "link12"); 238 239 bzero(r, sizeof(r)); 240 msg4.eh.ether_shost[5] = 1; 241 ng_errors(PASS); 242 ng_send_data("a", &msg4, sizeof(msg4)); 243 ATF_CHECK_ERRNO(ELOOP, errno != 0); /* loop might be detected */ 244 ng_errors(FAIL); 245 for (i = 0; i < 10; i++) /* don't run forever */ 246 if (!ng_handle_event(50, &r)) 247 break; 248 ATF_CHECK(r[0] == 0 && r[1] == 1); 249 250 ng_shutdown("bridge1:"); 251 ng_shutdown("bridge2:"); 252 } 253 254 ATF_TC(many_unicasts); 255 ATF_TC_HEAD(many_unicasts, conf) 256 { 257 atf_tc_set_md_var(conf, "require.user", "root"); 258 } 259 260 ATF_TC_BODY(many_unicasts, dummy) 261 { 262 int r[4], i; 263 const int HOOKS = 1000; 264 struct gettable rm; 265 266 ng_init(); 267 ng_errors(PASS); 268 ng_shutdown("bridge:"); 269 ng_errors(FAIL); 270 271 ng_mkpeer(".", "a", "bridge", "link0"); 272 ng_name("a", "bridge"); 273 ng_register_data("a", get_data0); 274 275 /* learn MAC */ 276 bzero(r, sizeof(r)); 277 msg4.eh.ether_shost[3] = 0xff; 278 ng_send_data("a", &msg4, sizeof(msg4)); 279 ng_handle_events(50, &r); 280 ATF_CHECK(r[0] == 0); 281 282 /* use learned MAC as destination */ 283 msg4.eh.ether_shost[3] = 0; 284 msg4.eh.ether_dhost[3] = 0xff; 285 286 /* now send */ 287 bzero(r, sizeof(r)); 288 for (i = 1; i <= HOOKS; i++) 289 { 290 char hook[20]; 291 292 snprintf(hook, sizeof(hook), "link%d", i); 293 ng_connect(".", hook, "bridge:", hook); 294 ng_register_data(hook, get_data2); 295 296 msg4.eh.ether_shost[4] = i >> 8; 297 msg4.eh.ether_shost[5] = i & 0xff; 298 ng_errors(PASS); 299 ng_send_data(hook, &msg4, sizeof(msg4)); 300 ng_errors(FAIL); 301 if (errno != 0) 302 break; 303 ng_handle_events(50, &r); 304 } 305 ATF_CHECK(r[0] == HOOKS && r[2] == 0); 306 307 /* inspect mac table */ 308 ng_register_msg(get_tablesize); 309 rm.cnt = 0; 310 ng_errors(PASS); 311 rm.tok = ng_send_msg("bridge:", "gettable"); 312 ng_errors(FAIL); 313 if (rm.tok == (u_int32_t)-1) 314 { 315 ATF_CHECK_ERRNO(ENOBUFS, 1); 316 atf_tc_expect_fail("response too large"); 317 } 318 ng_handle_events(50, &rm); 319 ATF_CHECK(rm.cnt == HOOKS + 1); 320 atf_tc_expect_pass(); 321 322 ng_shutdown("bridge:"); 323 } 324 325 ATF_TC(many_broadcasts); 326 ATF_TC_HEAD(many_broadcasts, conf) 327 { 328 atf_tc_set_md_var(conf, "require.user", "root"); 329 } 330 331 ATF_TC_BODY(many_broadcasts, dummy) 332 { 333 int r[4], i; 334 const int HOOKS = 1000; 335 336 ng_init(); 337 ng_errors(PASS); 338 ng_shutdown("bridge:"); 339 ng_errors(FAIL); 340 341 ng_mkpeer(".", "a", "bridge", "link0"); 342 ng_name("a", "bridge"); 343 ng_register_data("a", get_data0); 344 345 /* learn MAC */ 346 bzero(r, sizeof(r)); 347 msg4.eh.ether_shost[3] = 0xff; 348 ng_send_data("a", &msg4, sizeof(msg4)); 349 ng_handle_events(50, &r); 350 ATF_CHECK(r[0] == 0); 351 352 /* use broadcast MAC */ 353 msg4.eh.ether_shost[3] = 0; 354 memset(msg4.eh.ether_dhost, 0xff, sizeof(msg4.eh.ether_dhost)); 355 356 /* now send */ 357 bzero(r, sizeof(r)); 358 for (i = 1; i <= HOOKS; i++) 359 { 360 char hook[20]; 361 362 snprintf(hook, sizeof(hook), "link%d", i); 363 ng_connect(".", hook, "bridge:", hook); 364 ng_register_data(hook, get_data3); 365 366 msg4.eh.ether_shost[4] = i >> 8; 367 msg4.eh.ether_shost[5] = i & 0xff; 368 ng_errors(PASS); 369 ng_send_data(hook, &msg4, sizeof(msg4)); 370 ng_errors(FAIL); 371 if (errno != 0) 372 break; 373 ng_handle_events(50, &r); 374 } 375 ATF_CHECK(r[0] > 100 && r[3] > 100); 376 if (i < HOOKS) 377 atf_tc_expect_fail("netgraph queue full (%d)", i); 378 ATF_CHECK(r[0] == HOOKS); 379 atf_tc_expect_pass(); 380 381 ng_shutdown("bridge:"); 382 } 383 384 ATF_TC(uplink_private); 385 ATF_TC_HEAD(uplink_private, conf) 386 { 387 atf_tc_set_md_var(conf, "require.user", "root"); 388 } 389 390 ATF_TC_BODY(uplink_private, dummy) 391 { 392 int r[4]; 393 struct gettable rm; 394 395 ng_init(); 396 ng_errors(PASS); 397 ng_shutdown("bridge:"); 398 399 ng_mkpeer(".", "u1", "bridge", "uplink1"); 400 if (errno > 0) 401 atf_tc_skip("uplinks are not supported."); 402 ng_errors(FAIL); 403 ng_name("u1", "bridge"); 404 ng_register_data("u1", get_data1); 405 ng_connect(".", "u2", "bridge:", "uplink2"); 406 ng_register_data("u2", get_data2); 407 ng_connect(".", "l0", "bridge:", "link0"); 408 ng_register_data("l0", get_data0); 409 ng_connect(".", "l3", "bridge:", "link3"); 410 ng_register_data("l3", get_data3); 411 412 /* unknown unicast 0 from uplink1 */ 413 bzero(r, sizeof(r)); 414 msg4.eh.ether_shost[5] = 1; 415 ng_send_data("u1", &msg4, sizeof(msg4)); 416 ng_handle_events(50, &r); 417 ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1 && r[3] == 0); 418 419 /* unknown unicast 2 from link0 */ 420 bzero(r, sizeof(r)); 421 msg4.eh.ether_shost[5] = 0; 422 msg4.eh.ether_dhost[5] = 2; 423 ng_send_data("l0", &msg4, sizeof(msg4)); 424 ng_handle_events(50, &r); 425 ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 0); 426 427 /* known unicast 0 from uplink2 */ 428 bzero(r, sizeof(r)); 429 msg4.eh.ether_shost[5] = 2; 430 msg4.eh.ether_dhost[5] = 0; 431 ng_send_data("u2", &msg4, sizeof(msg4)); 432 ng_handle_events(50, &r); 433 ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0); 434 435 /* known unicast 0 from link3 */ 436 bzero(r, sizeof(r)); 437 msg4.eh.ether_shost[5] = 3; 438 msg4.eh.ether_dhost[5] = 0; 439 ng_send_data("l3", &msg4, sizeof(msg4)); 440 ng_handle_events(50, &r); 441 ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0); 442 443 /* (un)known unicast 2 from uplink1 */ 444 bzero(r, sizeof(r)); 445 msg4.eh.ether_shost[5] = 1; 446 msg4.eh.ether_dhost[5] = 2; 447 ng_send_data("u1", &msg4, sizeof(msg4)); 448 ng_handle_events(50, &r); 449 ATF_CHECK(r[0] == 0 && r[1] == 0 && r[2] == 1 && r[3] == 0); 450 451 /* (un)known unicast 2 from link0 */ 452 bzero(r, sizeof(r)); 453 msg4.eh.ether_shost[5] = 0; 454 ng_send_data("l0", &msg4, sizeof(msg4)); 455 ng_handle_events(50, &r); 456 ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 0); 457 458 /* unknown multicast 2 from uplink1 */ 459 bzero(r, sizeof(r)); 460 msg4.eh.ether_shost[5] = 1; 461 msg4.eh.ether_dhost[0] = 0xff; 462 ng_send_data("u1", &msg4, sizeof(msg4)); 463 ng_handle_events(50, &r); 464 ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1); 465 466 /* unknown multicast 2 from link0 */ 467 bzero(r, sizeof(r)); 468 msg4.eh.ether_shost[5] = 0; 469 ng_send_data("l0", &msg4, sizeof(msg4)); 470 ng_handle_events(50, &r); 471 ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1); 472 473 /* broadcast from uplink1 */ 474 bzero(r, sizeof(r)); 475 msg4.eh.ether_shost[5] = 1; 476 memset(msg4.eh.ether_dhost, 0xff, sizeof(msg4.eh.ether_dhost)); 477 ng_send_data("u1", &msg4, sizeof(msg4)); 478 ng_handle_events(50, &r); 479 ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1); 480 481 /* broadcast from link0 */ 482 bzero(r, sizeof(r)); 483 msg4.eh.ether_shost[5] = 0; 484 ng_send_data("l0", &msg4, sizeof(msg4)); 485 ng_handle_events(50, &r); 486 ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1); 487 488 /* inspect mac table */ 489 ng_register_msg(get_tablesize); 490 rm.tok = ng_send_msg("bridge:", "gettable"); 491 rm.cnt = 0; 492 ng_handle_events(50, &rm); 493 ATF_CHECK(rm.cnt == 2); 494 495 ng_shutdown("bridge:"); 496 } 497 498 ATF_TC(uplink_classic); 499 ATF_TC_HEAD(uplink_classic, conf) 500 { 501 atf_tc_set_md_var(conf, "require.user", "root"); 502 } 503 504 ATF_TC_BODY(uplink_classic, dummy) 505 { 506 int r[4]; 507 struct gettable rm; 508 509 ng_init(); 510 ng_errors(PASS); 511 ng_shutdown("bridge:"); 512 513 ng_mkpeer(".", "l0", "bridge", "link0"); 514 if (errno > 0) 515 atf_tc_skip("uplinks are not supported."); 516 ng_errors(FAIL); 517 ng_name("l0", "bridge"); 518 ng_register_data("l0", get_data0); 519 ng_connect(".", "u1", "bridge:", "uplink1"); 520 ng_register_data("u1", get_data1); 521 ng_connect(".", "u2", "bridge:", "uplink2"); 522 ng_register_data("u2", get_data2); 523 ng_connect(".", "l3", "bridge:", "link3"); 524 ng_register_data("l3", get_data3); 525 526 /* unknown unicast 0 from uplink1 */ 527 bzero(r, sizeof(r)); 528 msg4.eh.ether_shost[5] = 1; 529 ng_send_data("u1", &msg4, sizeof(msg4)); 530 ng_handle_events(50, &r); 531 ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1); 532 533 /* unknown unicast 2 from link0 */ 534 bzero(r, sizeof(r)); 535 msg4.eh.ether_shost[5] = 0; 536 msg4.eh.ether_dhost[5] = 2; 537 ng_send_data("l0", &msg4, sizeof(msg4)); 538 ng_handle_events(50, &r); 539 ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1); 540 541 /* known unicast 0 from uplink2 */ 542 bzero(r, sizeof(r)); 543 msg4.eh.ether_shost[5] = 2; 544 msg4.eh.ether_dhost[5] = 0; 545 ng_send_data("u2", &msg4, sizeof(msg4)); 546 ng_handle_events(50, &r); 547 ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0); 548 549 /* known unicast 0 from link3 */ 550 bzero(r, sizeof(r)); 551 msg4.eh.ether_shost[5] = 3; 552 msg4.eh.ether_dhost[5] = 0; 553 ng_send_data("l3", &msg4, sizeof(msg4)); 554 ng_handle_events(50, &r); 555 ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 0 && r[3] == 0); 556 557 /* (un)known unicast 2 from uplink1 */ 558 bzero(r, sizeof(r)); 559 msg4.eh.ether_shost[5] = 1; 560 msg4.eh.ether_dhost[5] = 2; 561 ng_send_data("u1", &msg4, sizeof(msg4)); 562 ng_handle_events(50, &r); 563 ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1); 564 565 /* (un)known unicast 2 from link0 */ 566 bzero(r, sizeof(r)); 567 msg4.eh.ether_shost[5] = 0; 568 ng_send_data("l0", &msg4, sizeof(msg4)); 569 ng_handle_events(50, &r); 570 ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1); 571 572 /* unknown multicast 2 from uplink1 */ 573 bzero(r, sizeof(r)); 574 msg4.eh.ether_shost[5] = 1; 575 msg4.eh.ether_dhost[0] = 0xff; 576 ng_send_data("u1", &msg4, sizeof(msg4)); 577 ng_handle_events(50, &r); 578 ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1); 579 580 /* unknown multicast 2 from link0 */ 581 bzero(r, sizeof(r)); 582 msg4.eh.ether_shost[5] = 0; 583 ng_send_data("l0", &msg4, sizeof(msg4)); 584 ng_handle_events(50, &r); 585 ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1); 586 587 /* broadcast from uplink1 */ 588 bzero(r, sizeof(r)); 589 msg4.eh.ether_shost[5] = 1; 590 memset(msg4.eh.ether_dhost, 0xff, sizeof(msg4.eh.ether_dhost)); 591 ng_send_data("u1", &msg4, sizeof(msg4)); 592 ng_handle_events(50, &r); 593 ATF_CHECK(r[0] == 1 && r[1] == 0 && r[2] == 1 && r[3] == 1); 594 595 /* broadcast from link0 */ 596 bzero(r, sizeof(r)); 597 msg4.eh.ether_shost[5] = 0; 598 ng_send_data("l0", &msg4, sizeof(msg4)); 599 ng_handle_events(50, &r); 600 ATF_CHECK(r[0] == 0 && r[1] == 1 && r[2] == 1 && r[3] == 1); 601 602 /* inspect mac table */ 603 ng_register_msg(get_tablesize); 604 rm.tok = ng_send_msg("bridge:", "gettable"); 605 rm.cnt = 0; 606 ng_handle_events(50, &rm); 607 ATF_CHECK(rm.cnt == 2); 608 609 ng_shutdown("bridge:"); 610 } 611 612 ATF_TP_ADD_TCS(bridge) 613 { 614 ATF_TP_ADD_TC(bridge, basic); 615 ATF_TP_ADD_TC(bridge, loop); 616 ATF_TP_ADD_TC(bridge, persistence); 617 ATF_TP_ADD_TC(bridge, many_unicasts); 618 ATF_TP_ADD_TC(bridge, many_broadcasts); 619 ATF_TP_ADD_TC(bridge, uplink_private); 620 ATF_TP_ADD_TC(bridge, uplink_classic); 621 622 return atf_no_error(); 623 } 624 625 static inline void 626 _get_data(void *data, size_t len, void *ctx, int i) 627 { 628 int *cnt = ctx; 629 630 (void)data; 631 fprintf(stderr, "[%d] Got %zu bytes of data.\n", i, len); 632 cnt[i]++; 633 } 634 635 #define GD(x) static void \ 636 get_data##x(void *data, size_t len, void *ctx) {\ 637 _get_data(data, len, ctx, x); \ 638 } 639 640 GD(0) 641 GD(1) 642 GD(2) 643 GD(3) 644 645 static void 646 get_tablesize(char const *source, struct ng_mesg *msg, void *ctx) 647 { 648 struct gettable *rm = ctx; 649 struct ng_bridge_host_ary *gt = (void *)msg->data; 650 651 fprintf(stderr, "Response from %s to query %d\n", source, msg->header.token); 652 if (rm->tok == msg->header.token) 653 rm->cnt = gt->numHosts; 654 } 655