/* * Copyright (c) 2015 Avaya, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #undef NDEBUG #include #include #include #include #include "ovs-lldp.h" #include "ovstest.h" #define ETH_TYPE_LLDP 0x88cc /* Dummy MAC addresses */ char chassis_mac[ETHER_ADDR_LEN] = { 0x5e, 0x10, 0x8e, 0xe7, 0x84, 0xad }; uint8_t eth_src[ETHER_ADDR_LEN] = { 0x5e, 0x10, 0x8e, 0xe7, 0x84, 0xad }; /* LLDP multicast address */ static const uint8_t eth_addr_lldp[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x0e}; /* Count of tests run */ int num_tests = 0; /* * Helper function to validate port info */ static void check_received_port(struct lldpd_port *sport, struct lldpd_port *rport) { assert(rport->p_id_subtype == sport->p_id_subtype); assert(rport->p_id_len == sport->p_id_len); assert(strncmp(rport->p_id, sport->p_id, sport->p_id_len) == 0); assert(strcmp(rport->p_descr, sport->p_descr) == 0); return; } /* * Helper function to validate chassis info */ static void check_received_chassis(struct lldpd_chassis *schassis, struct lldpd_chassis *rchassis) { assert(rchassis->c_id_subtype == schassis->c_id_subtype); assert(rchassis->c_id_len == schassis->c_id_len); assert(strncmp(rchassis->c_id, schassis->c_id, schassis->c_id_len) == 0); assert(strcmp(rchassis->c_name, schassis->c_name) == 0); assert(strcmp(rchassis->c_descr, schassis->c_descr) == 0); assert(rchassis->c_cap_available == schassis->c_cap_available); assert(rchassis->c_cap_enabled == schassis->c_cap_enabled); return; } /* * Helper function to validate auto-attach info */ static void check_received_aa(struct lldpd_port *sport, struct lldpd_port *rport, struct lldpd_aa_isid_vlan_maps_tlv *smap) { struct lldpd_aa_isid_vlan_maps_tlv *received_map; int i = 0; assert(rport->p_element.type == sport->p_element.type); assert(rport->p_element.mgmt_vlan == sport->p_element.mgmt_vlan); assert(rport->p_element.system_id.system_mac[0] == sport->p_element.system_id.system_mac[0]); assert(rport->p_element.system_id.system_mac[1] == sport->p_element.system_id.system_mac[1]); assert(rport->p_element.system_id.system_mac[2] == sport->p_element.system_id.system_mac[2]); assert(rport->p_element.system_id.system_mac[3] == sport->p_element.system_id.system_mac[3]); assert(rport->p_element.system_id.system_mac[4] == sport->p_element.system_id.system_mac[4]); assert(rport->p_element.system_id.system_mac[5] == sport->p_element.system_id.system_mac[5]); assert(rport->p_element.system_id.conn_type == sport->p_element.system_id.conn_type); assert(rport->p_element.system_id.smlt_id == sport->p_element.system_id.smlt_id); assert(rport->p_element.system_id.mlt_id[0] == sport->p_element.system_id.mlt_id[0]); assert(rport->p_element.system_id.mlt_id[1] == sport->p_element.system_id.mlt_id[1]); /* Should receive 2 mappings */ assert(!list_is_empty(&rport->p_isid_vlan_maps.m_entries)); /* For each received isid/vlan mapping */ LIST_FOR_EACH (received_map, m_entries, &rport->p_isid_vlan_maps.m_entries) { /* Validate against mapping sent */ assert(smap[i].isid_vlan_data.status == received_map->isid_vlan_data.status); assert(smap[i].isid_vlan_data.vlan == received_map->isid_vlan_data.vlan); assert(smap[i].isid_vlan_data.isid[0] == received_map->isid_vlan_data.isid[0]); assert(smap[i].isid_vlan_data.isid[1] == received_map->isid_vlan_data.isid[1]); assert(smap[i].isid_vlan_data.isid[2] == received_map->isid_vlan_data.isid[2]); /* Next mapping sent */ i++; } assert(i == 2); return; } /* * Validate basic send/receive processing */ static int test_aa_send(void) { struct lldp *lldp; struct lldpd_hardware hardware; struct lldpd_chassis chassis; struct lldpd_chassis *nchassis = NULL; struct lldpd_port *nport = NULL; struct lldpd_hardware *hw = NULL; struct lldpd_chassis *ch = NULL; struct lldpd_aa_isid_vlan_maps_tlv map_init[2]; struct lldpd_aa_isid_vlan_maps_tlv map[2]; uint32_t stub[512 / 4]; struct dp_packet packet; int n; /* Prepare data used to construct and validate LLDPPDU */ hardware.h_lport.p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME; hardware.h_lport.p_id = "FastEthernet 1/5"; hardware.h_lport.p_id_len = strlen(hardware.h_lport.p_id); hardware.h_lport.p_descr = "Fake port description"; hardware.h_lport.p_mfs = 1516; /* Auto attach element discovery info */ hardware.h_lport.p_element.type = LLDP_TLV_AA_ELEM_TYPE_TAG_CLIENT; hardware.h_lport.p_element.mgmt_vlan = 0xCDC; hardware.h_lport.p_element.system_id.system_mac[0] = 0x1; hardware.h_lport.p_element.system_id.system_mac[1] = 0x2; hardware.h_lport.p_element.system_id.system_mac[2] = 0x3; hardware.h_lport.p_element.system_id.system_mac[3] = 0x4; hardware.h_lport.p_element.system_id.system_mac[4] = 0x5; hardware.h_lport.p_element.system_id.system_mac[5] = 0x6; hardware.h_lport.p_element.system_id.conn_type = 0x5; hardware.h_lport.p_element.system_id.smlt_id = 0x3CC; hardware.h_lport.p_element.system_id.mlt_id[0] = 0xB; hardware.h_lport.p_element.system_id.mlt_id[1] = 0xE; /* Local chassis info */ chassis.c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR; chassis.c_id = chassis_mac; chassis.c_id_len = ETHER_ADDR_LEN; chassis.c_name = "Dummy chassis"; chassis.c_descr = "Long dummy chassis description"; chassis.c_cap_available = LLDP_CAP_BRIDGE; chassis.c_cap_enabled = LLDP_CAP_BRIDGE; /* ISID/VLAN mappings */ map_init[0].isid_vlan_data.status = 0xC; map_init[0].isid_vlan_data.vlan = 0x64; map_init[0].isid_vlan_data.isid[0] = 1; map_init[0].isid_vlan_data.isid[1] = 2; map_init[0].isid_vlan_data.isid[2] = 3; map_init[1].isid_vlan_data.status = 0xD; map_init[1].isid_vlan_data.vlan = 0xF; map_init[1].isid_vlan_data.isid[0] = 4; map_init[1].isid_vlan_data.isid[1] = 5; map_init[1].isid_vlan_data.isid[2] = 6; /* Prepare an empty packet buffer */ dp_packet_use_stub(&packet, stub, sizeof stub); dp_packet_clear(&packet); /* Create a dummy lldp instance */ lldp = lldp_create_dummy(); if ((lldp == NULL) || (lldp->lldpd == NULL) || (lldp->lldpd->g_hardware.h_entries.next == NULL)) { printf("Error: unable to create dummy lldp instance"); return 1; } /* Populate instance with local chassis info */ hw = (struct lldpd_hardware *) lldp->lldpd->g_hardware.h_entries.next; ch = hw->h_lport.p_chassis; ch->c_id_subtype = chassis.c_id_subtype; ch->c_id = chassis.c_id; ch->c_id_len = chassis.c_id_len; ch->c_name = chassis.c_name; ch->c_descr = chassis.c_descr; ch->c_cap_available = chassis.c_cap_available; ch->c_cap_enabled = chassis.c_cap_enabled; /* Populate instance with local port info */ hw->h_lport.p_id_subtype = hardware.h_lport.p_id_subtype; hw->h_lport.p_id = hardware.h_lport.p_id; hw->h_lport.p_id_len = strlen(hw->h_lport.p_id); hw->h_lport.p_descr = hardware.h_lport.p_descr; hw->h_lport.p_mfs = hardware.h_lport.p_mfs; /* Populate instance with auto attach element discovery info */ hw->h_lport.p_element.type = hardware.h_lport.p_element.type; hw->h_lport.p_element.mgmt_vlan = hardware.h_lport.p_element.mgmt_vlan; hw->h_lport.p_element.system_id.system_mac[0] = hardware.h_lport.p_element.system_id.system_mac[0]; hw->h_lport.p_element.system_id.system_mac[1] = hardware.h_lport.p_element.system_id.system_mac[1]; hw->h_lport.p_element.system_id.system_mac[2] = hardware.h_lport.p_element.system_id.system_mac[2]; hw->h_lport.p_element.system_id.system_mac[3] = hardware.h_lport.p_element.system_id.system_mac[3]; hw->h_lport.p_element.system_id.system_mac[4] = hardware.h_lport.p_element.system_id.system_mac[4]; hw->h_lport.p_element.system_id.system_mac[5] = hardware.h_lport.p_element.system_id.system_mac[5]; hw->h_lport.p_element.system_id.conn_type = hardware.h_lport.p_element.system_id.conn_type; hw->h_lport.p_element.system_id.smlt_id = hardware.h_lport.p_element.system_id.smlt_id; hw->h_lport.p_element.system_id.mlt_id[0] = hardware.h_lport.p_element.system_id.mlt_id[0]; hw->h_lport.p_element.system_id.mlt_id[1] = hardware.h_lport.p_element.system_id.mlt_id[1]; /* Populate instance with two auto attach isid/vlan mappings */ map[0].isid_vlan_data.status = map_init[0].isid_vlan_data.status; map[0].isid_vlan_data.vlan = map_init[0].isid_vlan_data.vlan; map[0].isid_vlan_data.isid[0] = map_init[0].isid_vlan_data.isid[0]; map[0].isid_vlan_data.isid[1] = map_init[0].isid_vlan_data.isid[1]; map[0].isid_vlan_data.isid[2] = map_init[0].isid_vlan_data.isid[2]; map[1].isid_vlan_data.status = map_init[1].isid_vlan_data.status; map[1].isid_vlan_data.vlan = map_init[1].isid_vlan_data.vlan; map[1].isid_vlan_data.isid[0] = map_init[1].isid_vlan_data.isid[0]; map[1].isid_vlan_data.isid[1] = map_init[1].isid_vlan_data.isid[1]; map[1].isid_vlan_data.isid[2] = map_init[1].isid_vlan_data.isid[2]; list_init(&hw->h_lport.p_isid_vlan_maps.m_entries); list_push_back(&hw->h_lport.p_isid_vlan_maps.m_entries, &map[0].m_entries); list_push_back(&hw->h_lport.p_isid_vlan_maps.m_entries, &map[1].m_entries); /* Construct LLDPPDU (including Ethernet header) */ eth_compose(&packet, eth_addr_lldp, eth_src, ETH_TYPE_LLDP, 0); n = lldp_send(lldp->lldpd, hw, &packet); if (n == 0) { printf("Error: unable to build packet\n"); return 1; } /* Decode the constructed LLDPPDU */ assert(lldp_decode(NULL, packet.data_, packet.size_, hw, &nchassis, &nport) != -1); /* Expecting returned pointers to allocated structures */ if (!nchassis || !nport) { printf("Error: unable to decode packet"); return 1; } /* Verify chassis values */ check_received_chassis(&chassis, nchassis); /* Verify port values */ check_received_port(&hardware.h_lport, nport); /* Verify auto attach values */ check_received_aa(&hardware.h_lport, nport, map_init); return 0; } static void test_aa_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) { int num_errors = 0; /* Make sure we emit valid auto-attach LLDPPDUs */ num_tests++; num_errors += test_aa_send(); /* Add more tests here */ printf("executed %d tests, %d errors\n", num_tests, num_errors); exit(num_errors != 0); } OVSTEST_REGISTER("test-aa", test_aa_main);