1 #include "rtnetlink.hpp" 2 3 #include <linux/netlink.h> 4 #include <linux/rtnetlink.h> 5 6 #include <stdplus/raw.hpp> 7 8 #include <gtest/gtest.h> 9 10 namespace phosphor::network::netlink 11 { 12 13 TEST(IntfFromRtm, SmallMsg) 14 { 15 EXPECT_THROW(intfFromRtm("1"), std::runtime_error); 16 } 17 18 TEST(IntfFromRtm, NoAttrs) 19 { 20 struct 21 { 22 ifinfomsg hdr __attribute__((aligned(NLMSG_ALIGNTO))); 23 } msg; 24 msg.hdr.ifi_index = 1; 25 msg.hdr.ifi_flags = 2; 26 EXPECT_EQ(intfFromRtm(stdplus::raw::asView<char>(msg)), 27 (InterfaceInfo{.idx = 1, .flags = 2})); 28 } 29 30 TEST(IntfFromRtm, AllAttrs) 31 { 32 struct 33 { 34 ifinfomsg hdr __attribute__((aligned(NLMSG_ALIGNTO))); 35 rtattr addr_hdr __attribute__((aligned((RTA_ALIGNTO)))); 36 char addr[6] 37 __attribute__((aligned((RTA_ALIGNTO)))) = {0, 1, 2, 3, 4, 5}; 38 rtattr name_hdr __attribute__((aligned((RTA_ALIGNTO)))); 39 char name[5] __attribute__((aligned((RTA_ALIGNTO)))) = "eth0"; 40 rtattr mtu_hdr __attribute__((aligned((RTA_ALIGNTO)))); 41 unsigned mtu __attribute__((aligned((RTA_ALIGNTO)))) = 50; 42 } msg; 43 msg.hdr.ifi_index = 1; 44 msg.hdr.ifi_flags = 2; 45 msg.addr_hdr.rta_type = IFLA_ADDRESS; 46 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr)); 47 msg.name_hdr.rta_type = IFLA_IFNAME; 48 msg.name_hdr.rta_len = RTA_LENGTH(sizeof(msg.name)); 49 msg.mtu_hdr.rta_type = IFLA_MTU; 50 msg.mtu_hdr.rta_len = RTA_LENGTH(sizeof(msg.mtu)); 51 52 auto info = intfFromRtm(stdplus::raw::asView<char>(msg)); 53 auto expected = InterfaceInfo{.idx = 1, 54 .flags = 2, 55 .name = "eth0", 56 .mac = ether_addr{0, 1, 2, 3, 4, 5}, 57 .mtu = 50}; 58 EXPECT_EQ(info, expected); 59 } 60 61 TEST(AddrFromRtm, MissingAddr) 62 { 63 struct 64 { 65 alignas(NLMSG_ALIGNTO) ifaddrmsg ifa = {}; 66 } msg; 67 EXPECT_THROW(addrFromRtm(stdplus::raw::asView<char>(msg)), 68 std::runtime_error); 69 } 70 71 TEST(AddrFromRtm, Regular) 72 { 73 struct 74 { 75 alignas(NLMSG_ALIGNTO) ifaddrmsg ifa; 76 alignas(NLMSG_ALIGNTO) rtattr addr_hdr; 77 alignas(NLMSG_ALIGNTO) uint8_t addr[4] = {192, 168, 1, 20}; 78 } msg; 79 msg.ifa.ifa_family = AF_INET; 80 msg.ifa.ifa_prefixlen = 28; 81 msg.ifa.ifa_flags = 4; 82 msg.ifa.ifa_scope = 3; 83 msg.ifa.ifa_index = 10; 84 msg.addr_hdr.rta_type = IFA_ADDRESS; 85 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr)); 86 87 auto ret = addrFromRtm(stdplus::raw::asView<char>(msg)); 88 EXPECT_EQ(msg.ifa.ifa_flags, ret.flags); 89 EXPECT_EQ(msg.ifa.ifa_scope, ret.scope); 90 EXPECT_EQ(msg.ifa.ifa_index, ret.ifidx); 91 EXPECT_EQ((IfAddr{in_addr{hton(0xc0a80114)}, 28}), ret.ifaddr); 92 } 93 94 TEST(AddrFromRtm, ExtraFlags) 95 { 96 struct 97 { 98 alignas(NLMSG_ALIGNTO) ifaddrmsg ifa = {}; 99 alignas(NLMSG_ALIGNTO) rtattr flags_hdr; 100 alignas(NLMSG_ALIGNTO) uint32_t flags = 0xff00ff00; 101 alignas(NLMSG_ALIGNTO) rtattr addr_hdr; 102 alignas(NLMSG_ALIGNTO) uint8_t addr[16] = {}; 103 } msg; 104 msg.ifa.ifa_family = AF_INET6; 105 msg.flags_hdr.rta_type = IFA_FLAGS; 106 msg.flags_hdr.rta_len = RTA_LENGTH(sizeof(msg.flags)); 107 msg.addr_hdr.rta_type = IFA_ADDRESS; 108 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr)); 109 110 auto ret = addrFromRtm(stdplus::raw::asView<char>(msg)); 111 EXPECT_EQ(0xff00ff00, ret.flags); 112 } 113 114 TEST(NeighFromRtm, MissingAddr) 115 { 116 struct 117 { 118 alignas(NLMSG_ALIGNTO) ndmsg ndm = {}; 119 } msg; 120 121 EXPECT_EQ((NeighborInfo{}), neighFromRtm(stdplus::raw::asView<char>(msg))); 122 } 123 124 TEST(NeighFromRtm, NoMac) 125 { 126 struct 127 { 128 alignas(NLMSG_ALIGNTO) ndmsg ndm; 129 alignas(NLMSG_ALIGNTO) rtattr addr_hdr; 130 alignas(NLMSG_ALIGNTO) uint8_t addr[4] = {192, 168, 1, 20}; 131 } msg; 132 msg.ndm.ndm_family = AF_INET; 133 msg.ndm.ndm_state = 4; 134 msg.addr_hdr.rta_type = NDA_DST; 135 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr)); 136 137 auto ret = neighFromRtm(stdplus::raw::asView<char>(msg)); 138 EXPECT_EQ(msg.ndm.ndm_state, ret.state); 139 EXPECT_EQ((in_addr{hton(0xc0a80114)}), ret.addr); 140 EXPECT_FALSE(ret.mac); 141 } 142 143 TEST(NeighFromRtm, Full) 144 { 145 struct 146 { 147 alignas(NLMSG_ALIGNTO) ndmsg ndm; 148 alignas(NLMSG_ALIGNTO) rtattr addr_hdr; 149 alignas(NLMSG_ALIGNTO) uint8_t addr[4] = {192, 168, 1, 20}; 150 alignas(NLMSG_ALIGNTO) rtattr mac_hdr; 151 alignas(NLMSG_ALIGNTO) uint8_t mac[6] = {1, 2, 3, 4, 5, 6}; 152 } msg; 153 msg.ndm.ndm_family = AF_INET; 154 msg.addr_hdr.rta_type = NDA_DST; 155 msg.addr_hdr.rta_len = RTA_LENGTH(sizeof(msg.addr)); 156 msg.mac_hdr.rta_type = NDA_LLADDR; 157 msg.mac_hdr.rta_len = RTA_LENGTH(sizeof(msg.mac)); 158 159 auto ret = neighFromRtm(stdplus::raw::asView<char>(msg)); 160 EXPECT_EQ((in_addr{hton(0xc0a80114)}), ret.addr); 161 EXPECT_EQ((ether_addr{1, 2, 3, 4, 5, 6}), ret.mac); 162 } 163 164 } // namespace phosphor::network::netlink 165