| /* SPDX-License-Identifier: LGPL-2.1-only */ |
| /* |
| * Author: Susant Sahani <[email protected]> |
| * Copyright (c) 2018 Red Hat, Inc. |
| */ |
| |
| #include "nl-default.h" |
| |
| #include <linux/netlink.h> |
| |
| #include <netlink/route/link.h> |
| #include <netlink/route/link/sit.h> |
| #include <netlink/route/link/bonding.h> |
| #include <netlink/route/link/bridge.h> |
| #include <netlink/route/link/ip6tnl.h> |
| #include <netlink/route/link/ipgre.h> |
| #include <netlink/route/link/ipip.h> |
| #include <netlink/route/link/ipvlan.h> |
| #include <netlink/route/link/ipvti.h> |
| #include <netlink/route/link/macsec.h> |
| #include <netlink/route/link/macvlan.h> |
| #include <netlink/route/link/macvtap.h> |
| #include <netlink/route/link/veth.h> |
| #include <netlink/route/link/vlan.h> |
| #include <netlink/route/link/vrf.h> |
| #include <netlink/route/link/vxlan.h> |
| |
| #include "cksuite-all.h" |
| |
| /*****************************************************************************/ |
| |
| static void _nltst_delete_link2(const char *ifname) |
| { |
| _nltst_delete_link(NULL, ifname); |
| } |
| #define _nltst_auto_delete_link _nl_auto(_nltst_auto_delete_link_fcn) |
| _NL_AUTO_DEFINE_FCN_TYPED0(const char *, _nltst_auto_delete_link_fcn, |
| _nltst_delete_link2); |
| |
| /*****************************************************************************/ |
| |
| START_TEST(cache_and_clone) |
| { |
| _nl_auto_nl_socket struct nl_sock *sk = NULL; |
| _nl_auto_nl_cache struct nl_cache *link_cache = NULL; |
| _nl_auto_free struct nl_object **links_all = NULL; |
| static const struct { |
| const char *ifname; |
| const char *kind; |
| bool add; |
| } links[] = { |
| { |
| .ifname = "xbr0", |
| .kind = "bridge", |
| .add = true, |
| }, |
| { |
| .ifname = "xdummy0", |
| .kind = "dummy", |
| .add = true, |
| }, |
| { |
| .ifname = "xbond0", |
| .kind = "bond", |
| .add = true, |
| }, |
| { |
| .ifname = "lo", |
| .kind = NULL, |
| .add = false, |
| }, |
| }; |
| size_t i; |
| int r; |
| |
| for (i = 0; i < _NL_N_ELEMENTS(links); i++) { |
| if (links[i].add) |
| _nltst_add_link(NULL, links[i].ifname, links[i].kind, |
| NULL); |
| } |
| |
| sk = _nltst_socket(NETLINK_ROUTE); |
| |
| r = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache); |
| ck_assert_int_eq(r, 0); |
| |
| r = nl_cache_refill(sk, link_cache); |
| ck_assert_int_eq(r, 0); |
| |
| for (i = 0; i < _NL_N_ELEMENTS(links); i++) { |
| _nl_auto_rtnl_link struct rtnl_link *link_clone = NULL; |
| struct rtnl_link *link; |
| |
| link = _nltst_cache_get_link(link_cache, links[i].ifname); |
| ck_assert_ptr_nonnull(link); |
| |
| ck_assert_str_eq(rtnl_link_get_name(link), links[i].ifname); |
| |
| if (_nl_streq(links[i].ifname, "lo")) |
| ck_assert_int_eq(rtnl_link_get_ifindex(link), 1); |
| else |
| ck_assert_int_gt(rtnl_link_get_ifindex(link), 1); |
| |
| link_clone = (struct rtnl_link *)nl_object_clone( |
| (struct nl_object *)link); |
| ck_assert(link_clone); |
| |
| _nltst_object_identical(link, link_clone); |
| } |
| |
| links_all = _nltst_cache_get_all(link_cache, NULL); |
| for (i = 0; links_all[i]; i++) { |
| struct rtnl_link *link = (struct rtnl_link *)links_all[i]; |
| _nl_auto_rtnl_link struct rtnl_link *link_clone = NULL; |
| |
| link_clone = (struct rtnl_link *)nl_object_clone( |
| (struct nl_object *)link); |
| ck_assert(link_clone); |
| |
| _nltst_object_identical(link, link_clone); |
| } |
| } |
| END_TEST |
| |
| /*****************************************************************************/ |
| |
| START_TEST(test_create_iface) |
| { |
| const int TEST_IDX = _i; |
| _nl_auto_nl_socket struct nl_sock *sk = _nltst_socket(NETLINK_ROUTE); |
| _nl_auto_rtnl_link struct rtnl_link *link = NULL; |
| _nl_auto_rtnl_link struct rtnl_link *link2 = NULL; |
| _nl_auto_rtnl_link struct rtnl_link *peer = NULL; |
| _nltst_auto_delete_link const char *IFNAME_DUMMY = NULL; |
| _nltst_auto_delete_link const char *IFNAME = "ifname"; |
| int ifindex_dummy; |
| uint32_t u32; |
| int r; |
| |
| switch (TEST_IDX) { |
| case 0: |
| link = _nltst_assert(rtnl_link_bridge_alloc()); |
| rtnl_link_set_name(link, IFNAME); |
| break; |
| case 1: |
| link = _nltst_assert(rtnl_link_vxlan_alloc()); |
| rtnl_link_set_name(link, IFNAME); |
| _nltst_assert_retcode(rtnl_link_vxlan_set_id(link, 128)); |
| break; |
| case 2: |
| link = _nltst_assert(rtnl_link_alloc()); |
| rtnl_link_set_type(link, "ifb"); |
| rtnl_link_set_name(link, IFNAME); |
| break; |
| case 3: |
| link = _nltst_assert(rtnl_link_ipgre_alloc()); |
| rtnl_link_set_name(link, IFNAME); |
| _nltst_assert_retcode(rtnl_link_ipgre_set_local( |
| link, _nltst_inet4("192.168.254.12"))); |
| _nltst_assert_retcode(rtnl_link_ipgre_set_remote( |
| link, _nltst_inet4("192.168.254.13"))); |
| _nltst_assert_retcode(rtnl_link_ipgre_set_ttl(link, 64)); |
| break; |
| case 4: |
| link = _nltst_assert(rtnl_link_ip6_tnl_alloc()); |
| rtnl_link_set_name(link, IFNAME); |
| _nltst_assert_retcode(rtnl_link_ip6_tnl_set_local( |
| link, _nltst_inet6p("2607:f0d0:1002:51::4"))); |
| _nltst_assert_retcode(rtnl_link_ip6_tnl_set_remote( |
| link, _nltst_inet6p("2607:f0d0:1002:52::5"))); |
| break; |
| case 5: |
| link = _nltst_assert(rtnl_link_ipgretap_alloc()); |
| rtnl_link_set_name(link, IFNAME); |
| _nltst_assert_retcode(rtnl_link_ipgre_set_local( |
| link, _nltst_inet4("10.211.55.10"))); |
| _nltst_assert_retcode(rtnl_link_ipgre_set_remote( |
| link, _nltst_inet4("10.133.6.33"))); |
| _nltst_assert_retcode(rtnl_link_ipgre_set_ttl(link, 64)); |
| break; |
| case 6: |
| link = _nltst_assert(rtnl_link_ipvti_alloc()); |
| rtnl_link_set_name(link, IFNAME); |
| _nltst_assert_retcode(rtnl_link_ipvti_set_local( |
| link, _nltst_inet4("192.168.254.12"))); |
| _nltst_assert_retcode(rtnl_link_ipvti_set_remote( |
| link, _nltst_inet4("192.168.254.13"))); |
| break; |
| case 7: |
| link = _nltst_assert(rtnl_link_sit_alloc()); |
| rtnl_link_set_name(link, IFNAME); |
| _nltst_assert_retcode(rtnl_link_sit_set_local( |
| link, _nltst_inet4("192.168.254.12"))); |
| _nltst_assert_retcode(rtnl_link_sit_set_remote( |
| link, _nltst_inet4("192.168.254.13"))); |
| _nltst_assert_retcode(rtnl_link_sit_set_ttl(link, 64)); |
| break; |
| case 8: |
| link = _nltst_assert(rtnl_link_ipip_alloc()); |
| rtnl_link_set_name(link, IFNAME); |
| _nltst_assert_retcode(rtnl_link_ipip_set_local( |
| link, _nltst_inet4("192.168.254.12"))); |
| _nltst_assert_retcode(rtnl_link_ipip_set_remote( |
| link, _nltst_inet4("192.168.254.13"))); |
| _nltst_assert_retcode(rtnl_link_ipip_set_ttl(link, 64)); |
| break; |
| case 9: |
| link = _nltst_assert(rtnl_link_bond_alloc()); |
| rtnl_link_set_name(link, IFNAME); |
| break; |
| case 10: |
| IFNAME_DUMMY = "ci-dummy"; |
| _nltst_add_link(sk, IFNAME_DUMMY, "dummy", &ifindex_dummy); |
| |
| link = _nltst_assert(rtnl_link_macvtap_alloc()); |
| rtnl_link_set_link(link, ifindex_dummy); |
| rtnl_link_set_name(link, IFNAME); |
| _nltst_assert_retcode(rtnl_link_macvtap_set_mode( |
| link, rtnl_link_macvtap_str2mode("bridge"))); |
| break; |
| case 11: |
| IFNAME_DUMMY = "ci-dummy"; |
| _nltst_add_link(sk, IFNAME_DUMMY, "dummy", &ifindex_dummy); |
| |
| link = _nltst_assert(rtnl_link_macvlan_alloc()); |
| rtnl_link_set_link(link, ifindex_dummy); |
| rtnl_link_set_name(link, IFNAME); |
| break; |
| case 12: |
| IFNAME_DUMMY = "ci-dummy"; |
| _nltst_add_link(sk, IFNAME_DUMMY, "dummy", &ifindex_dummy); |
| |
| link = _nltst_assert(rtnl_link_vlan_alloc()); |
| rtnl_link_set_link(link, ifindex_dummy); |
| rtnl_link_set_name(link, IFNAME); |
| _nltst_assert_retcode(rtnl_link_vlan_set_id(link, 10)); |
| break; |
| case 13: |
| IFNAME_DUMMY = "ci-dummy"; |
| _nltst_add_link(sk, IFNAME_DUMMY, "dummy", &ifindex_dummy); |
| |
| link = _nltst_assert(rtnl_link_macsec_alloc()); |
| rtnl_link_set_link(link, ifindex_dummy); |
| rtnl_link_set_name(link, IFNAME); |
| _nltst_assert_retcode(rtnl_link_macsec_set_port(link, 10)); |
| _nltst_assert_retcode(rtnl_link_macsec_set_encrypt(link, 1)); |
| _nltst_assert_retcode( |
| rtnl_link_macsec_set_replay_protect(link, 1)); |
| _nltst_assert_retcode(rtnl_link_macsec_set_window(link, 200)); |
| break; |
| case 14: |
| IFNAME_DUMMY = "ci-dummy"; |
| _nltst_add_link(sk, IFNAME_DUMMY, "dummy", &ifindex_dummy); |
| |
| link = _nltst_assert(rtnl_link_ipvlan_alloc()); |
| rtnl_link_set_link(link, ifindex_dummy); |
| _nltst_assert_retcode(rtnl_link_ipvlan_set_mode( |
| link, rtnl_link_ipvlan_str2mode("l2"))); |
| rtnl_link_set_name(link, IFNAME); |
| break; |
| case 15: |
| link = _nltst_assert(rtnl_link_vrf_alloc()); |
| rtnl_link_set_name(link, IFNAME); |
| _nltst_assert_retcode(rtnl_link_vrf_set_tableid(link, 10)); |
| break; |
| case 16: { |
| link = _nltst_assert(rtnl_link_veth_alloc()); |
| rtnl_link_set_name(link, IFNAME); |
| peer = _nltst_assert(rtnl_link_veth_get_peer(link)); |
| rtnl_link_set_name(peer, "ci-veth-peer"); |
| } break; |
| default: |
| ck_assert_msg(0, "unexpected TEST_IDX=%d", _i); |
| break; |
| } |
| |
| r = rtnl_link_add(sk, link, NLM_F_CREATE); |
| if (r == -NLE_OPNOTSUPP) { |
| /* Hm, no kernel module? Skip the test. */ |
| _nltst_assert_link_not_exists(IFNAME); |
| IFNAME = NULL; |
| return; |
| } |
| _nltst_assert_retcode(r); |
| |
| _nltst_assert_link_exists(IFNAME); |
| |
| switch (TEST_IDX) { |
| case 15: |
| _nltst_get_link(sk, IFNAME, NULL, &link2); |
| _nltst_assert_retcode(rtnl_link_vrf_get_tableid(link2, &u32)); |
| ck_assert_int_eq(u32, 10); |
| break; |
| case 16: |
| _nltst_assert_link_exists("ci-veth-peer"); |
| if (_nltst_rand_bool()) |
| IFNAME = "ci-veth-peer"; |
| break; |
| } |
| } |
| END_TEST |
| |
| /*****************************************************************************/ |
| |
| static void _route_init(int addr_family, struct nl_sock **sk, |
| struct nl_cache **cache) |
| { |
| ck_assert(sk && !*sk); |
| ck_assert(cache && !*cache); |
| |
| *sk = _nltst_socket(NETLINK_ROUTE); |
| *cache = _nltst_rtnl_route_alloc_cache(*sk, addr_family); |
| } |
| |
| START_TEST(route_1) |
| { |
| _nl_auto_nl_socket struct nl_sock *sk = NULL; |
| _nl_auto_nl_cache struct nl_cache *cache = NULL; |
| |
| if (_nltst_skip_no_iproute2("route_1")) |
| return; |
| |
| _nltst_add_link(NULL, "v1", "dummy", NULL); |
| _nltst_system("ip -d link set v1 up"); |
| |
| _route_init(AF_INET6, &sk, &cache); |
| |
| _nltst_assert_route_cache(cache, "fe80::/64", "6 fe80::*/128", |
| "ff00::/8"); |
| } |
| END_TEST |
| |
| /*****************************************************************************/ |
| |
| Suite *make_nl_netns_suite(void) |
| { |
| Suite *suite = suite_create("netns"); |
| TCase *tc = tcase_create("Core"); |
| |
| tcase_add_checked_fixture(tc, nltst_netns_fixture_setup, |
| nltst_netns_fixture_teardown); |
| tcase_add_test(tc, cache_and_clone); |
| tcase_add_loop_test(tc, test_create_iface, 0, 17); |
| tcase_add_test(tc, route_1); |
| suite_add_tcase(suite, tc); |
| |
| return suite; |
| } |