From: Dennis Flynn <drfl...@avaya.com> The following enhancements to the auto-attach feature are provided
- Support recent modifications to the AA element discovery TLV - Support recent Avaya Organizationally Unique ID (OUI) change. (This will change to IEEE assigned OUI once AA standard has been ratified) - Remove some Avaya specific #defines The primary purpose of this commit is to catch up with the latest changes made to the auto attach TLVs as the Auto Attach feature progresses through the 802.1Q IEEE standards committee. Most notably this includes some minor rework of the AA element discovery TLV and a recent change to the Avaya OUI value. Signed-off-by: Dennis Flynn <drfl...@avaya.com> diff --git a/lib/lldp/aa-structs.h b/lib/lldp/aa-structs.h index 567a831..983c74c 100644 --- a/lib/lldp/aa-structs.h +++ b/lib/lldp/aa-structs.h @@ -26,12 +26,14 @@ struct lldp_aa_element_system_id { uint8_t system_mac[6]; uint16_t conn_type; - uint16_t smlt_id; - uint8_t mlt_id[2]; + uint16_t rsvd; + uint8_t rsvd2[2]; }; struct lldpd_aa_element_tlv { uint16_t type; + uint16_t vlan_tagging; + uint16_t auto_prov_mode; uint16_t mgmt_vlan; struct lldp_aa_element_system_id system_id; }; diff --git a/lib/lldp/lldp-tlv.h b/lib/lldp/lldp-tlv.h index 237414d..2b94828 100644 --- a/lib/lldp/lldp-tlv.h +++ b/lib/lldp/lldp-tlv.h @@ -36,7 +36,7 @@ #define LLDP_TLV_ORG_DOT1 {0x00, 0x80, 0xc2} #define LLDP_TLV_ORG_DOT3 {0x00, 0x12, 0x0f} #define LLDP_TLV_ORG_MED {0x00, 0x12, 0xbb} -#define LLDP_TLV_ORG_AVAYA {0x00, 0x40, 0x0D} +#define LLDP_TLV_ORG_AVAYA {0x00, 0x04, 0x0D} #define LLDP_TLV_ORG_DCBX {0x00, 0x1b, 0x21} #define LLDP_TLV_DOT1_PVID 1 @@ -61,16 +61,26 @@ #define LLDP_TLV_MED_IV_MODEL 10 #define LLDP_TLV_MED_IV_ASSET 11 -#define LLDP_TLV_AA_ELEMENT_SUBTYPE 0x08 -#define LLDP_TLV_AA_ISID_VLAN_ASGNS_SUBTYPE 0x09 +#define LLDP_TLV_AA_ELEMENT_SUBTYPE 0x0b +#define LLDP_TLV_AA_ISID_VLAN_ASGNS_SUBTYPE 0x0c #define LLDP_TLV_AA_ISID_VLAN_DIGEST_LENGTH 32 -#define LLDP_TLV_AA_ELEM_TYPE_UNKNOWN 1 -#define LLDP_TLV_AA_ELEM_TYPE_SERVER 2 -#define LLDP_TLV_AA_ELEM_TYPE_PROXY 3 -#define LLDP_TLV_AA_ELEM_TYPE_UNTAG_CLIENT 4 -#define LLDP_TLV_AA_ELEM_TYPE_TAG_CLIENT 5 -#define LLDP_TLV_AA_ELEM_TYPE_SERV_NO_AUTH 6 -#define LLDP_TLV_AA_ELEM_TYPE_PROXY_NO_AUTH 7 + +#define LLDP_TLV_AA_ELEM_TYPE_UNKNOWN 1 +#define LLDP_TLV_AA_ELEM_TYPE_SERVER 2 +#define LLDP_TLV_AA_ELEM_TYPE_PROXY 3 +#define LLDP_TLV_AA_ELEM_TYPE_SERV_NO_AUTH 4 +#define LLDP_TLV_AA_ELEM_TYPE_PROXY_NO_AUTH 5 +#define LLDP_TLV_AA_ELEM_TYPE_CLIENT_WIRELESS_ACCESS_POINT_TYPE1 6 +#define LLDP_TLV_AA_ELEM_TYPE_CLIENT_WIRELESS_ACCESS_POINT_TYPE2 7 +#define LLDP_TLV_AA_ELEM_TYPE_CLIENT_SWITCH 8 +#define LLDP_TLV_AA_ELEM_TYPE_CLIENT_ROUTER 9 +#define LLDP_TLV_AA_ELEM_TYPE_CLIENT_IP_PHONE 10 +#define LLDP_TLV_AA_ELEM_TYPE_CLIENT_IP_CAMERA 11 +#define LLDP_TLV_AA_ELEM_TYPE_CLIENT_IP_VIDEO 12 +#define LLDP_TLV_AA_ELEM_TYPE_CLIENT_SECURITY_DEVICE 13 +#define LLDP_TLV_AA_ELEM_TYPE_CLIENT_VIRTUAL_SWITCH 14 +#define LLDP_TLV_AA_ELEM_TYPE_CLIENT_SERVER_ENDPOINT 15 + #define LLDP_TLV_AA_ELEM_CONN_TYPE_SINGLE 0 #define LLDP_TLV_AA_ELEM_CONN_TYPE_MLT 1 #define LLDP_TLV_AA_ELEM_CONN_TYPE_SLT 2 diff --git a/lib/lldp/lldp.c b/lib/lldp/lldp.c index d77bcd0..493c2ff 100644 --- a/lib/lldp/lldp.c +++ b/lib/lldp/lldp.c @@ -235,53 +235,69 @@ lldp_send(struct lldpd *global OVS_UNUSED, lldp_tlv_end(p, start); } - /* Add Auto Attach tlvs to packet */ + /* Add Auto Attach tlvs V3.1 to packet. LLDP FA element v3.1 format: + TLV Type[127] TLV Length[50 octets] Avaya OUI[00-04-0D] Subtype[11] + 7 bits 9 bits 3 octets 1 octet + HMAC-SHA Digest Element Type State Mgmt VLAN Rsvd System ID + 32 octets 6 bits 6 bits 12 bits 1 octet 10 octets + */ /* AA-ELEMENT */ if (port->p_element.type != 0) { - u_int8_t aa_element_first_byte; - u_int8_t aa_element_second_byte = 0; + u_int16_t aa_element_first_word = 0; + u_int16_t aa_element_second_word = 0; + u_int16_t aa_element_state = 0; u_int8_t aa_elem_sys_id_first_byte; u_int8_t aa_elem_sys_id_second_byte; - /* Element type should be first 4 most significant bits, so bitwise OR - * that with the first 4 bits of the 12-bit-wide mgmt_vlan - */ - aa_element_first_byte = (((port->p_element.type & 0xF) << 4) | - ((port->p_element.mgmt_vlan >> 8) & 0xF)); - - /* Second byte should just be the remaining 8 bits of .mgmt_vlan */ - aa_element_second_byte = port->p_element.mgmt_vlan & 0x0FF; - - /* .conn_type should be 4 most sig. bits, so bitwise OR that - * with the first 4 bits of the 12-bit-wide .smlt_id - */ + /* Link VLAN Tagging Requirements (bit 1), + * Automatic Provisioning Mode (bit 2/3) (left to right, 1 based) */ + aa_element_state = ((port->p_element.vlan_tagging & 0x1) << 5) | + ((port->p_element.auto_prov_mode & 0x3) << 3); + + /* Element first word should be first 6 most significant bits of + * element type, bitwise OR that with the next 6 bits of the state, + * bitwise OR with the first 4 bits of mgmt vlan id. + * Element type should be LLDP_TLV_AA_ELEM_TYPE_VIRTUAL_SWITCH for + * AA client */ + aa_element_first_word = (port->p_element.type << 10) | + (aa_element_state << 4) | + ((port->p_element.mgmt_vlan & 0x0F00)>> 8); + + /* Element second type should be the first 8 most significant bits + * of the remaining 8 bits of mgmt vlan id. */ + aa_element_second_word = (port->p_element.mgmt_vlan & 0xFF) << 8; + + /* System id first byte should be first 3 most significant bits of + * connecion type, bitwise OR that with the device state and bitwise + * OR that with the first 2 most significant bitsof rsvd (10 bits). */ aa_elem_sys_id_first_byte = - ((port->p_element.system_id.conn_type & 0xF) << 4) | - ((port->p_element.system_id.smlt_id >> 8) & 0xF); + ((port->p_element.system_id.conn_type & 0x7) << 5) | + ((port->p_element.system_id.rsvd >> 8) & 0x3); - /* Second byte should just be the remaining 8 bits of .smlt_id */ - aa_elem_sys_id_second_byte = port->p_element.system_id.smlt_id & 0x0FF; + /* Second byte should just be the remaining 8 bits of 10 bits rsvd */ + aa_elem_sys_id_second_byte = + (port->p_element.system_id.rsvd & 0xFF); + + memset(msg_auth_digest, 0, sizeof msg_auth_digest); lldp_tlv_start(p, LLDP_TLV_ORG, &start); dp_packet_put(p, avaya, sizeof avaya); lldp_tlv_put_u8(p, LLDP_TLV_AA_ELEMENT_SUBTYPE); - lldp_tlv_put_u8(p, aa_element_first_byte); - lldp_tlv_put_u8(p, aa_element_second_byte); + dp_packet_put(p, msg_auth_digest, sizeof msg_auth_digest); + lldp_tlv_put_u16(p, aa_element_first_word); + lldp_tlv_put_u16(p, aa_element_second_word); dp_packet_put(p, &port->p_element.system_id.system_mac, sizeof port->p_element.system_id.system_mac); lldp_tlv_put_u8(p, aa_elem_sys_id_first_byte); lldp_tlv_put_u8(p, aa_elem_sys_id_second_byte); - dp_packet_put(p, &port->p_element.system_id.mlt_id, - sizeof port->p_element.system_id.mlt_id); + dp_packet_put(p, &port->p_element.system_id.rsvd2, + sizeof port->p_element.system_id.rsvd2); lldp_tlv_end(p, start); } if (!list_is_empty(&port->p_isid_vlan_maps)) { - int j; - for (j = 0; j < LLDP_TLV_AA_ISID_VLAN_DIGEST_LENGTH; j++) { - msg_auth_digest[j] = 0; - } + memset(msg_auth_digest, 0, sizeof msg_auth_digest); lldp_tlv_start(p, LLDP_TLV_ORG, &start); dp_packet_put(p, avaya, sizeof avaya); @@ -314,6 +330,7 @@ lldp_send(struct lldpd *global OVS_UNUSED, if (!hardware->h_lport.p_lastframe || hardware->h_lport.p_lastframe->size != lldp_len || memcmp(hardware->h_lport.p_lastframe->frame, lldp, lldp_len)) { + struct lldpd_frame *frame = xmalloc(sizeof *frame + lldp_len); frame->size = lldp_len; memcpy(frame->frame, lldp, lldp_len); @@ -327,8 +344,8 @@ lldp_send(struct lldpd *global OVS_UNUSED, int lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s, - struct lldpd_hardware *hardware, struct lldpd_chassis **newchassis, - struct lldpd_port **newport) + struct lldpd_hardware *hardware, struct lldpd_chassis **newchassis, + struct lldpd_port **newport) { struct lldpd_chassis *chassis; struct lldpd_port *port; @@ -372,6 +389,7 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s, "received on %s", hardware->h_ifname); goto malformed; } + PEEK_DISCARD(ETH_ADDR_LEN); /* Skip source address */ if (PEEK_UINT16 != ETHERTYPE_LLDP) { VLOG_INFO("non LLDP frame received on %s", hardware->h_ifname); @@ -498,34 +516,57 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s, /* LLDP-MED */ hardware->h_rx_unrecognized_cnt++; } else if (memcmp(avaya_oid, orgid, sizeof orgid) == 0) { - u_int16_t aa_element_word; - u_int16_t aa_status_vlan_word; + u_int32_t aa_element_dword; u_int16_t aa_system_id_word; + u_int16_t aa_status_vlan_word; + u_int8_t aa_element_state; unsigned short num_mappings; switch(tlv_subtype) { case LLDP_TLV_AA_ELEMENT_SUBTYPE: - aa_element_word = PEEK_UINT16; + PEEK_BYTES(&msg_auth_digest, sizeof msg_auth_digest); + + aa_element_dword = PEEK_UINT32; + + /* Type is first 6 most-significant bits of + * aa_element_dword */ + port->p_element.type = aa_element_dword >> 26; - /* Type is first 4 most-significant bits */ - port->p_element.type = aa_element_word >> 12; + /* State is 6 most significant bits of aa_element_dword */ + aa_element_state = (aa_element_dword >> 20) & 0x3F; - /* mgmt_vlan is last 12 bits */ - port->p_element.mgmt_vlan = aa_element_word & 0x0FFF; - VLOG_INFO("Element type: %X, Mgmt vlan: %X", + /* vlan tagging requirement is the bit 1(left to right) + * of the 6 bits state (1 based) */ + port->p_element.vlan_tagging = + (aa_element_state >> 5) & 0x1; + + /* Automatic provision mode is the bit 2/3(left to right) + * of the 6 bits state (1 based) */ + port->p_element.auto_prov_mode = + (aa_element_state >> 3) & 0x3; + + /* mgmt_vlan is the 12 bits of aa_element_dword from + * bit 12 */ + port->p_element.mgmt_vlan = + (aa_element_dword >> 8) & 0xFFF; + VLOG_INFO("Element type: %X, vlan tagging %X, " + "auto prov mode %x, Mgmt vlan: %X", port->p_element.type, + port->p_element.vlan_tagging, + port->p_element.auto_prov_mode, port->p_element.mgmt_vlan); + PEEK_BYTES(&port->p_element.system_id.system_mac, sizeof port->p_element.system_id.system_mac); VLOG_INFO("System mac: "ETH_ADDR_FMT, - ETH_ADDR_ARGS(port->p_element.system_id.system_mac)); + ETH_ADDR_ARGS(port->p_element.system_id.system_mac)); aa_system_id_word = PEEK_UINT16; port->p_element.system_id.conn_type = - aa_system_id_word >> 12; - port->p_element.system_id.smlt_id = - aa_system_id_word & 0x0FFF; - PEEK_BYTES(&port->p_element.system_id.mlt_id, - sizeof port->p_element.system_id.mlt_id); + aa_system_id_word >> 13; + port->p_element.system_id.rsvd = aa_system_id_word & + 0x03FF; + PEEK_BYTES(&port->p_element.system_id.rsvd2, + sizeof port->p_element.system_id.rsvd2); break; case LLDP_TLV_AA_ISID_VLAN_ASGNS_SUBTYPE: diff --git a/lib/ovs-lldp.c b/lib/ovs-lldp.c index a30eca5..db97648 100644 --- a/lib/ovs-lldp.c +++ b/lib/ovs-lldp.c @@ -822,16 +822,15 @@ lldp_create(const struct netdev *netdev, hw->h_lport.p_id_len = strlen(netdev_get_name(netdev)); /* Auto Attach element tlv */ - hw->h_lport.p_element.type = LLDP_TLV_AA_ELEM_TYPE_TAG_CLIENT; + hw->h_lport.p_element.type = LLDP_TLV_AA_ELEM_TYPE_CLIENT_VIRTUAL_SWITCH; hw->h_lport.p_element.mgmt_vlan = 0; memcpy(&hw->h_lport.p_element.system_id.system_mac, lchassis->c_id, lchassis->c_id_len); hw->h_lport.p_element.system_id.conn_type = LLDP_TLV_AA_ELEM_CONN_TYPE_SINGLE; - - hw->h_lport.p_element.system_id.smlt_id = 0; - hw->h_lport.p_element.system_id.mlt_id[0] = 0; - hw->h_lport.p_element.system_id.mlt_id[1] = 0; + hw->h_lport.p_element.system_id.rsvd = 0; + hw->h_lport.p_element.system_id.rsvd2[0] = 0; + hw->h_lport.p_element.system_id.rsvd2[1] = 0; list_init(&hw->h_lport.p_isid_vlan_maps); list_init(&lldp->lldpd->g_hardware); @@ -908,15 +907,15 @@ lldp_create_dummy(void) hw->h_lport.p_id_len = strlen(hw->h_lport.p_id); /* Auto Attach element tlv */ - hw->h_lport.p_element.type = LLDP_TLV_AA_ELEM_TYPE_TAG_CLIENT; + hw->h_lport.p_element.type = LLDP_TLV_AA_ELEM_TYPE_CLIENT_VIRTUAL_SWITCH; hw->h_lport.p_element.mgmt_vlan = 0; memcpy(&hw->h_lport.p_element.system_id.system_mac, lchassis->c_id, lchassis->c_id_len); hw->h_lport.p_element.system_id.conn_type = LLDP_TLV_AA_ELEM_CONN_TYPE_SINGLE; - hw->h_lport.p_element.system_id.smlt_id = 0; - hw->h_lport.p_element.system_id.mlt_id[0] = 0; - hw->h_lport.p_element.system_id.mlt_id[1] = 0; + hw->h_lport.p_element.system_id.rsvd = 0; + hw->h_lport.p_element.system_id.rsvd2[0] = 0; + hw->h_lport.p_element.system_id.rsvd2[1] = 0; list_init(&hw->h_lport.p_isid_vlan_maps); list_init(&lldp->lldpd->g_hardware); diff --git a/tests/test-aa.c b/tests/test-aa.c index 4fb2618..9dabce1 100644 --- a/tests/test-aa.c +++ b/tests/test-aa.c @@ -98,12 +98,12 @@ check_received_aa(struct lldpd_port *sport, 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]); + assert(rport->p_element.system_id.rsvd == + sport->p_element.system_id.rsvd); + assert(rport->p_element.system_id.rsvd2[0] == + sport->p_element.system_id.rsvd2[0]); + assert(rport->p_element.system_id.rsvd2[1] == + sport->p_element.system_id.rsvd2[1]); /* Should receive 2 mappings */ assert(!list_is_empty(&rport->p_isid_vlan_maps)); @@ -160,7 +160,8 @@ test_aa_send(void) 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.type = + LLDP_TLV_AA_ELEM_TYPE_CLIENT_VIRTUAL_SWITCH; 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; @@ -170,9 +171,9 @@ test_aa_send(void) 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; + hardware.h_lport.p_element.system_id.rsvd = 0x3CC; + hardware.h_lport.p_element.system_id.rsvd2[0] = 0xB; + hardware.h_lport.p_element.system_id.rsvd2[1] = 0xE; /* Local chassis info */ chassis.c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR; @@ -242,12 +243,12 @@ test_aa_send(void) 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]; + hw->h_lport.p_element.system_id.rsvd = + hardware.h_lport.p_element.system_id.rsvd; + hw->h_lport.p_element.system_id.rsvd2[0] = + hardware.h_lport.p_element.system_id.rsvd2[0]; + hw->h_lport.p_element.system_id.rsvd2[1] = + hardware.h_lport.p_element.system_id.rsvd2[1]; /* Populate instance with two auto attach isid/vlan mappings */ map[0].isid_vlan_data.status = map_init[0].isid_vlan_data.status; -- 1.8.3.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev