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