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