LCOV - code coverage report
Current view: top level - libsystemd-network - test-lldp.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 140 148 94.6 %
Date: 2019-08-22 15:41:25 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <arpa/inet.h>
       4             : #include <errno.h>
       5             : #include <net/ethernet.h>
       6             : #include <stdio.h>
       7             : #include <string.h>
       8             : #include <unistd.h>
       9             : 
      10             : #include "sd-event.h"
      11             : #include "sd-lldp.h"
      12             : 
      13             : #include "alloc-util.h"
      14             : #include "fd-util.h"
      15             : #include "lldp-network.h"
      16             : #include "macro.h"
      17             : #include "string-util.h"
      18             : #include "tests.h"
      19             : 
      20             : #define TEST_LLDP_PORT "em1"
      21             : #define TEST_LLDP_TYPE_SYSTEM_NAME "systemd-lldp"
      22             : #define TEST_LLDP_TYPE_SYSTEM_DESC "systemd-lldp-desc"
      23             : 
      24             : static int test_fd[2] = { -1, -1 };
      25             : static int lldp_handler_calls;
      26             : 
      27           4 : int lldp_network_bind_raw_socket(int ifindex) {
      28           4 :         if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
      29           0 :                 return -errno;
      30             : 
      31           4 :         return test_fd[0];
      32             : }
      33             : 
      34           8 : static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) {
      35           8 :         lldp_handler_calls++;
      36           8 : }
      37             : 
      38           4 : static int start_lldp(sd_lldp **lldp, sd_event *e, sd_lldp_callback_t cb, void *cb_data) {
      39             :         int r;
      40             : 
      41           4 :         r = sd_lldp_new(lldp);
      42           4 :         if (r < 0)
      43           0 :                 return r;
      44             : 
      45           4 :         r = sd_lldp_set_ifindex(*lldp, 42);
      46           4 :         if (r < 0)
      47           0 :                 return r;
      48             : 
      49           4 :         r = sd_lldp_set_callback(*lldp, cb, cb_data);
      50           4 :         if (r < 0)
      51           0 :                 return r;
      52             : 
      53           4 :         r = sd_lldp_attach_event(*lldp, e, 0);
      54           4 :         if (r < 0)
      55           0 :                 return r;
      56             : 
      57           4 :         r = sd_lldp_start(*lldp);
      58           4 :         if (r < 0)
      59           0 :                 return r;
      60             : 
      61           4 :         return 0;
      62             : }
      63             : 
      64           4 : static int stop_lldp(sd_lldp *lldp) {
      65             :         int r;
      66             : 
      67           4 :         r = sd_lldp_stop(lldp);
      68           4 :         if (r < 0)
      69           0 :                 return r;
      70             : 
      71           4 :         r = sd_lldp_detach_event(lldp);
      72           4 :         if (r < 0)
      73           0 :                 return r;
      74             : 
      75           4 :         sd_lldp_unref(lldp);
      76           4 :         safe_close(test_fd[1]);
      77             : 
      78           4 :         return 0;
      79             : }
      80             : 
      81           1 : static void test_receive_basic_packet(sd_event *e) {
      82             : 
      83             :         static const uint8_t frame[] = {
      84             :                 /* Ethernet header */
      85             :                 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03,     /* Destination MAC */
      86             :                 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,     /* Source MAC */
      87             :                 0x88, 0xcc,                             /* Ethertype */
      88             :                 /* LLDP mandatory TLVs */
      89             :                 0x02, 0x07, 0x04, 0x00, 0x01, 0x02,     /* Chassis: MAC, 00:01:02:03:04:05 */
      90             :                 0x03, 0x04, 0x05,
      91             :                 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33,     /* Port: interface name, "1/3" */
      92             :                 0x06, 0x02, 0x00, 0x78,                 /* TTL: 120 seconds */
      93             :                 /* LLDP optional TLVs */
      94             :                 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74,     /* Port Description: "Port" */
      95             :                 0x0a, 0x03, 0x53, 0x59, 0x53,           /* System Name: "SYS" */
      96             :                 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00,     /* System Description: "foo" (NULL-terminated) */
      97             :                 0x00, 0x00                              /* End Of LLDPDU */
      98             :         };
      99             : 
     100             :         sd_lldp *lldp;
     101             :         sd_lldp_neighbor **neighbors;
     102             :         uint8_t type;
     103             :         const void *data;
     104             :         uint16_t ttl;
     105             :         size_t length;
     106             :         const char *str;
     107             : 
     108           1 :         lldp_handler_calls = 0;
     109           1 :         assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0);
     110             : 
     111           1 :         assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame));
     112           1 :         sd_event_run(e, 0);
     113           1 :         assert_se(lldp_handler_calls == 1);
     114           1 :         assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 1);
     115             : 
     116           1 :         assert_se(sd_lldp_neighbor_get_chassis_id(neighbors[0], &type, &data, &length) == 0);
     117           1 :         assert_se(type == SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS);
     118           1 :         assert_se(length == ETH_ALEN);
     119           1 :         assert_se(!memcmp(data, "\x00\x01\x02\x03\x04\x05", ETH_ALEN));
     120             : 
     121           1 :         assert_se(sd_lldp_neighbor_get_port_id(neighbors[0], &type, &data, &length) == 0);
     122           1 :         assert_se(type == SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME);
     123           1 :         assert_se(length == 3);
     124           1 :         assert_se(!memcmp(data, "1/3", 3));
     125             : 
     126           1 :         assert_se(sd_lldp_neighbor_get_port_description(neighbors[0], &str) == 0);
     127           1 :         assert_se(streq(str, "Port"));
     128             : 
     129           1 :         assert_se(sd_lldp_neighbor_get_system_name(neighbors[0], &str) == 0);
     130           1 :         assert_se(streq(str, "SYS"));
     131             : 
     132           1 :         assert_se(sd_lldp_neighbor_get_system_description(neighbors[0], &str) == 0);
     133           1 :         assert_se(streq(str, "foo"));
     134             : 
     135           1 :         assert_se(sd_lldp_neighbor_get_ttl(neighbors[0], &ttl) == 0);
     136           1 :         assert_se(ttl == 120);
     137             : 
     138           1 :         sd_lldp_neighbor_unref(neighbors[0]);
     139           1 :         free(neighbors);
     140             : 
     141           1 :         assert_se(stop_lldp(lldp) == 0);
     142           1 : }
     143             : 
     144           1 : static void test_receive_incomplete_packet(sd_event *e) {
     145             :         sd_lldp *lldp;
     146             :         sd_lldp_neighbor **neighbors;
     147           1 :         uint8_t frame[] = {
     148             :                 /* Ethernet header */
     149             :                 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03,     /* Destination MAC */
     150             :                 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,     /* Source MAC */
     151             :                 0x88, 0xcc,                             /* Ethertype */
     152             :                 /* LLDP mandatory TLVs */
     153             :                 0x02, 0x07, 0x04, 0x00, 0x01, 0x02,     /* Chassis: MAC, 00:01:02:03:04:05 */
     154             :                 0x03, 0x04, 0x05,
     155             :                 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33,     /* Port: interface name, "1/3" */
     156             :                                                         /* Missing TTL */
     157             :                 0x00, 0x00                              /* End Of LLDPDU */
     158             :         };
     159             : 
     160           1 :         lldp_handler_calls = 0;
     161           1 :         assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0);
     162             : 
     163           1 :         assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame));
     164           1 :         sd_event_run(e, 0);
     165           1 :         assert_se(lldp_handler_calls == 0);
     166           1 :         assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 0);
     167             : 
     168           1 :         assert_se(stop_lldp(lldp) == 0);
     169           1 : }
     170             : 
     171           1 : static void test_receive_oui_packet(sd_event *e) {
     172             :         sd_lldp *lldp;
     173             :         sd_lldp_neighbor **neighbors;
     174           1 :         uint8_t frame[] = {
     175             :                 /* Ethernet header */
     176             :                 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03,     /* Destination MAC */
     177             :                 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,     /* Source MAC */
     178             :                 0x88, 0xcc,                             /* Ethertype */
     179             :                 /* LLDP mandatory TLVs */
     180             :                 0x02, 0x07, 0x04, 0x00, 0x01, 0x02,     /* Chassis: MAC, 00:01:02:03:04:05 */
     181             :                 0x03, 0x04, 0x05,
     182             :                 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33,     /* Port TLV: interface name, "1/3" */
     183             :                 0x06, 0x02, 0x00, 0x78,                 /* TTL: 120 seconds */
     184             :                 /* LLDP optional TLVs */
     185             :                 0xfe, 0x06, 0x00, 0x80, 0xc2, 0x01,     /* Port VLAN ID: 0x1234 */
     186             :                 0x12, 0x34,
     187             :                 0xfe, 0x07, 0x00, 0x80, 0xc2, 0x02,     /* Port and protocol: flag 1, PPVID 0x7788 */
     188             :                 0x01, 0x77, 0x88,
     189             :                 0xfe, 0x0d, 0x00, 0x80, 0xc2, 0x03,     /* VLAN Name: ID 0x1234, name "Vlan51" */
     190             :                 0x12, 0x34, 0x06, 0x56, 0x6c, 0x61,
     191             :                 0x6e, 0x35, 0x31,
     192             :                 0xfe, 0x06, 0x00, 0x80, 0xc2, 0x06,     /* Management VID: 0x0102 */
     193             :                 0x01, 0x02,
     194             :                 0xfe, 0x09, 0x00, 0x80, 0xc2, 0x07,     /* Link aggregation: status 1, ID 0x00140012 */
     195             :                 0x01, 0x00, 0x14, 0x00, 0x12,
     196             :                 0xfe, 0x07, 0x00, 0x12, 0x0f, 0x02,     /* 802.3 Power via MDI: PSE, MDI enabled */
     197             :                 0x07, 0x01, 0x00,
     198             :                 0x00, 0x00                              /* End of LLDPDU */
     199             :         };
     200             : 
     201           1 :         lldp_handler_calls = 0;
     202           1 :         assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0);
     203             : 
     204           1 :         assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame));
     205           1 :         sd_event_run(e, 0);
     206           1 :         assert_se(lldp_handler_calls == 1);
     207           1 :         assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 1);
     208             : 
     209           1 :         assert_se(sd_lldp_neighbor_tlv_rewind(neighbors[0]) >= 0);
     210           1 :         assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_CHASSIS_ID) > 0);
     211           1 :         assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
     212           1 :         assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_PORT_ID) > 0);
     213           1 :         assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
     214           1 :         assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_TTL) > 0);
     215           1 :         assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
     216           1 :         assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID) > 0);
     217           1 :         assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
     218           1 :         assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID) > 0);
     219           1 :         assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
     220           1 :         assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME) > 0);
     221           1 :         assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
     222           1 :         assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID) > 0);
     223           1 :         assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
     224           1 :         assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION) > 0);
     225           1 :         assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
     226           1 :         assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_3, SD_LLDP_OUI_802_3_SUBTYPE_POWER_VIA_MDI) > 0);
     227           1 :         assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0);
     228           1 :         assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_END) > 0);
     229           1 :         assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) == 0);
     230             : 
     231           1 :         sd_lldp_neighbor_unref(neighbors[0]);
     232           1 :         free(neighbors);
     233             : 
     234           1 :         assert_se(stop_lldp(lldp) == 0);
     235           1 : }
     236             : 
     237           1 : static void test_multiple_neighbors_sorted(sd_event *e) {
     238             : 
     239             :         static const uint8_t frame1[] = {
     240             :                 /* Ethernet header */
     241             :                 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03,     /* Destination MAC */
     242             :                 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,     /* Source MAC */
     243             :                 0x88, 0xcc,                             /* Ethertype */
     244             :                 /* LLDP mandatory TLVs */
     245             :                 0x02, 0x04, 0x01, '1', '/', '2',        /* Chassis component: "1/2" */
     246             :                 0x04, 0x04, 0x02, '2', '/', '3',        /* Port component: "2/3" */
     247             :                 0x06, 0x02, 0x00, 0x78,                 /* TTL: 120 seconds */
     248             :                 0x00, 0x00                              /* End Of LLDPDU */
     249             :         };
     250             :         static const uint8_t frame2[] = {
     251             :                 /* Ethernet header */
     252             :                 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03,     /* Destination MAC */
     253             :                 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,     /* Source MAC */
     254             :                 0x88, 0xcc,                             /* Ethertype */
     255             :                 /* LLDP mandatory TLVs */
     256             :                 0x02, 0x04, 0x01, '2', '/', '1',        /* Chassis component: "2/1" */
     257             :                 0x04, 0x04, 0x02, '1', '/', '3',        /* Port component: "1/3" */
     258             :                 0x06, 0x02, 0x00, 0x78,                 /* TTL: 120 seconds */
     259             :                 0x00, 0x00                              /* End Of LLDPDU */
     260             :         };
     261             :         static const uint8_t frame3[] = {
     262             :                 /* Ethernet header */
     263             :                 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03,     /* Destination MAC */
     264             :                 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,     /* Source MAC */
     265             :                 0x88, 0xcc,                             /* Ethertype */
     266             :                 /* LLDP mandatory TLVs */
     267             :                 0x02, 0x05, 0x01, '2', '/', '1', '0',   /* Chassis component: "2/10" */
     268             :                 0x04, 0x04, 0x02, '1', '/', '0',        /* Port component: "1/0" */
     269             :                 0x06, 0x02, 0x00, 0x78,                 /* TTL: 120 seconds */
     270             :                 0x00, 0x00                              /* End Of LLDPDU */
     271             :         };
     272             :         static const uint8_t frame4[] = {
     273             :                 /* Ethernet header */
     274             :                 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03,     /* Destination MAC */
     275             :                 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,     /* Source MAC */
     276             :                 0x88, 0xcc,                             /* Ethertype */
     277             :                 /* LLDP mandatory TLVs */
     278             :                 0x02, 0x05, 0x01, '2', '/', '1', '9',   /* Chassis component: "2/19" */
     279             :                 0x04, 0x04, 0x02, '1', '/', '0',        /* Port component: "1/0" */
     280             :                 0x06, 0x02, 0x00, 0x78,                 /* TTL: 120 seconds */
     281             :                 0x00, 0x00                              /* End Of LLDPDU */
     282             :         };
     283             :         static const uint8_t frame5[] = {
     284             :                 /* Ethernet header */
     285             :                 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03,     /* Destination MAC */
     286             :                 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,     /* Source MAC */
     287             :                 0x88, 0xcc,                             /* Ethertype */
     288             :                 /* LLDP mandatory TLVs */
     289             :                 0x02, 0x04, 0x01, '1', '/', '2',        /* Chassis component: "1/2" */
     290             :                 0x04, 0x05, 0x02, '2', '/', '1', '0',   /* Port component: "2/10" */
     291             :                 0x06, 0x02, 0x00, 0x78,                 /* TTL: 120 seconds */
     292             :                 0x00, 0x00                              /* End Of LLDPDU */
     293             :         };
     294             :         static const uint8_t frame6[] = {
     295             :                 /* Ethernet header */
     296             :                 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03,     /* Destination MAC */
     297             :                 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,     /* Source MAC */
     298             :                 0x88, 0xcc,                             /* Ethertype */
     299             :                 /* LLDP mandatory TLVs */
     300             :                 0x02, 0x04, 0x01, '1', '/', '2',        /* Chassis component: "1/2" */
     301             :                 0x04, 0x05, 0x02, '2', '/', '3', '9',   /* Port component: "2/10" */
     302             :                 0x06, 0x02, 0x00, 0x78,                 /* TTL: 120 seconds */
     303             :                 0x00, 0x00                              /* End Of LLDPDU */
     304             :         };
     305             :         static const char* expected[] = {
     306             :                 /* ordered pairs of Chassis+Port */
     307             :                 "1/2", "2/10",
     308             :                 "1/2", "2/3",
     309             :                 "1/2", "2/39",
     310             :                 "2/1", "1/3",
     311             :                 "2/10", "1/0",
     312             :                 "2/19", "1/0",
     313             :         };
     314             : 
     315             :         sd_lldp *lldp;
     316             :         sd_lldp_neighbor **neighbors;
     317             :         int i;
     318             :         uint8_t type;
     319             :         const void *data;
     320             :         size_t length, expected_length;
     321             :         uint16_t ttl;
     322             : 
     323           1 :         lldp_handler_calls = 0;
     324           1 :         assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0);
     325             : 
     326           1 :         assert_se(write(test_fd[1], frame1, sizeof(frame1)) == sizeof(frame1));
     327           1 :         sd_event_run(e, 0);
     328           1 :         assert_se(write(test_fd[1], frame2, sizeof(frame2)) == sizeof(frame2));
     329           1 :         sd_event_run(e, 0);
     330           1 :         assert_se(write(test_fd[1], frame3, sizeof(frame3)) == sizeof(frame3));
     331           1 :         sd_event_run(e, 0);
     332           1 :         assert_se(write(test_fd[1], frame4, sizeof(frame4)) == sizeof(frame4));
     333           1 :         sd_event_run(e, 0);
     334           1 :         assert_se(write(test_fd[1], frame5, sizeof(frame5)) == sizeof(frame5));
     335           1 :         sd_event_run(e, 0);
     336           1 :         assert_se(write(test_fd[1], frame6, sizeof(frame6)) == sizeof(frame6));
     337           1 :         sd_event_run(e, 0);
     338           1 :         assert_se(lldp_handler_calls == 6);
     339             : 
     340           1 :         assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 6);
     341             : 
     342           7 :         for (i = 0; i < 6; i++) {
     343           6 :                 assert_se(sd_lldp_neighbor_get_chassis_id(neighbors[i], &type, &data, &length) == 0);
     344           6 :                 assert_se(type == SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT);
     345           6 :                 expected_length = strlen(expected[2 * i]);
     346           6 :                 assert_se(length == expected_length);
     347           6 :                 assert_se(memcmp(data, expected[2 * i], expected_length) == 0);
     348             : 
     349           6 :                 assert_se(sd_lldp_neighbor_get_port_id(neighbors[i], &type, &data, &length) == 0);
     350           6 :                 assert_se(type == SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT);
     351           6 :                 expected_length = strlen(expected[2 * i + 1]);
     352           6 :                 assert_se(length == expected_length);
     353           6 :                 assert_se(memcmp(data, expected[2 * i + 1], expected_length) == 0);
     354             : 
     355           6 :                 assert_se(sd_lldp_neighbor_get_ttl(neighbors[i], &ttl) == 0);
     356           6 :                 assert_se(ttl == 120);
     357             :         }
     358             : 
     359           7 :         for (i = 0; i < 6; i++)
     360           6 :                 sd_lldp_neighbor_unref(neighbors[i]);
     361           1 :         free(neighbors);
     362             : 
     363           1 :         assert_se(stop_lldp(lldp) == 0);
     364           1 : }
     365             : 
     366           1 : int main(int argc, char *argv[]) {
     367           2 :         _cleanup_(sd_event_unrefp) sd_event *e = NULL;
     368             : 
     369           1 :         test_setup_logging(LOG_DEBUG);
     370             : 
     371             :         /* LLDP reception tests */
     372           1 :         assert_se(sd_event_new(&e) == 0);
     373           1 :         test_receive_basic_packet(e);
     374           1 :         test_receive_incomplete_packet(e);
     375           1 :         test_receive_oui_packet(e);
     376           1 :         test_multiple_neighbors_sorted(e);
     377             : 
     378           1 :         return 0;
     379             : }

Generated by: LCOV version 1.14