Commit a62a8c85 authored by Adam Wujek's avatar Adam Wujek 💬 Committed by Grzegorz Daniluk

lib/lldp: try to change some fields and make it more dynamic

Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parent c9c30aab
...@@ -2,7 +2,10 @@ ...@@ -2,7 +2,10 @@
* This work is part of the White Rabbit project * This work is part of the White Rabbit project
* *
* Copyright (C) 2011 GSI (www.gsi.de) * Copyright (C) 2011 GSI (www.gsi.de)
* Copyright (C) 2017 CERN
*
* Author: Cesar Prados <c.prados@gsi.de> * Author: Cesar Prados <c.prados@gsi.de>
* Author: Adam Wujek <adam.wujek@cern.ch>
* *
* LLDP transmit-only station * LLDP transmit-only station
* *
...@@ -17,9 +20,10 @@ ...@@ -17,9 +20,10 @@
#include "endpoint.h" #include "endpoint.h"
#include "ipv4.h" #include "ipv4.h"
#include "shell.h" #include "shell.h"
#include "syscon.h"
#include <wrpc.h> /*needed for htons()*/ #include <wrpc.h> /*needed for htons()*/
static char lldpdu[LLDP_PKT_LEN]; static uint8_t lldpdu[LLDP_MAX_PKT_LEN];
static uint16_t lldpdu_len; static uint16_t lldpdu_len;
/* tx-only socket */ /* tx-only socket */
...@@ -31,105 +35,165 @@ static struct wrpc_socket __static_lldp_socket = { ...@@ -31,105 +35,165 @@ static struct wrpc_socket __static_lldp_socket = {
static struct wrpc_socket *lldp_socket; static struct wrpc_socket *lldp_socket;
static struct wr_sockaddr addr; static struct wr_sockaddr addr;
static void lldp_header_tlv(int tlv_type) { extern char wrc_hw_name[HW_NAME_LENGTH];
//lldpdu_len = tlv_offset[tlv_type]; static void lldp_header_tlv(uint8_t tlv_type, uint8_t tlv_len)
{
lldpdu[lldpdu_len] = tlv_type << 1; lldpdu[lldpdu_len] = tlv_type << 1;
lldpdu[lldpdu_len + LLDP_SUBTYPE] = tlv_type_len[tlv_type]; lldpdu[lldpdu_len + LLDP_SUBTYPE] = tlv_len;
lldpdu_len += 2; lldpdu_len += LLDP_HEADER;
}
static void fill_mac(uint8_t *tlv, uint8_t type)
{
*tlv = type;
/* write MAC after subtype byte */
get_mac_addr(tlv + LLDP_SUBTYPE);
} }
static void lldp_add_tlv(int tlv_type) { static void lldp_add_tlv(int tlv_type) {
unsigned char mac[6]; uint8_t mac[6];
unsigned char ipWR[4]; unsigned char ipWR[4];
int tlv_len = 0;
switch(tlv_type) { switch (tlv_type) {
case END_LLDP: case END_LLDP:
/* End TLV */
/* header */ /* header */
lldp_header_tlv(tlv_type); lldp_header_tlv(tlv_type, tlv_len);
/* End TLV */
memcpy(lldpdu + lldpdu_len, 0x0, tlv_type_len[tlv_type]);
break; break;
case CHASSIS_ID: case CHASSIS_ID:
tlv_len = CHASSIS_ID_TLV_LEN;
/* header */ /* header */
lldp_header_tlv(tlv_type); lldp_header_tlv(tlv_type, tlv_len);
/* TLV Chassis Component */ /* TLV Chassis Component */
lldpdu[lldpdu_len] = 4; fill_mac(&lldpdu[lldpdu_len], CHASSIS_ID_TYPE_MAC);
get_mac_addr(mac);
memcpy(lldpdu + (lldpdu_len + LLDP_SUBTYPE), mac, 6);
break; break;
case PORT_ID: case PORT_ID:
tlv_len = PORT_ID_TLV_LEN;
/* header */ /* header */
lldp_header_tlv(tlv_type); lldp_header_tlv(tlv_type, tlv_len);
/* TLV Interce Alias */ /* TLV portID */
lldpdu[lldpdu_len] = LLDP_ID_SUBTYPE_MAC; fill_mac(&lldpdu[lldpdu_len], PORT_ID_SUBTYPE_MAC);
get_mac_addr(mac);
memcpy(lldpdu + (lldpdu_len + LLDP_SUBTYPE), mac, 6);
break; break;
case TTL: case TTL:
tlv_len = TTL_ID_TLV_LEN;
/* header */ /* header */
lldp_header_tlv(tlv_type); lldp_header_tlv(tlv_type, tlv_len);
/* TLV Time to Live */ /* TLV Time to Live */
lldpdu[lldpdu_len + LLDP_SUBTYPE] = 0x20; /* sec */ /* use LLDP_TX_TICK_INTERVAL in seconds times 4 */
lldpdu[lldpdu_len + TTL_BYTE_MSB] =
(((LLDP_TX_TICK_INTERVAL / 1000) * 4) >> 8)
& 0xff;
lldpdu[lldpdu_len + TTL_BYTE_LSB] =
((LLDP_TX_TICK_INTERVAL / 1000) * 4) & 0xff;
break; break;
case PORT: case PORT:
tlv_len = strlen(PORT_NAME) + 1;
/* header */ /* header */
lldp_header_tlv(tlv_type); lldp_header_tlv(tlv_type, tlv_len);
/* TLV Info srting */ strcpy((char *)lldpdu + lldpdu_len, PORT_NAME);
if (HAS_IP) {
getIP(ipWR);
char buf[32];
format_ip(buf, ipWR);
strcpy(lldpdu + lldpdu_len, buf);
}
break; break;
case SYS_NAME: case SYS_NAME:
{
/* TODO get host system name from wr-core outer world */
/* NOTE: according to 802.1AB-2005 9.5.6.2 and then
* IETF RFC 3418:
* "If the name is unknown, the value is
* the zero-length string."
* However, we put the IP, if not set MAC to be able to
* identify a system */
char buf[32];
getIP(ipWR);
if (HAS_IP && memcmp(ipWR, "\0\0\0\0", 4)) {
/* NOTE: no subtype */
format_ip(buf, ipWR);
tlv_len = strlen((char *)buf);
strcpy((char *)(lldpdu + lldpdu_len + LLDP_HEADER),
(char *)buf);
} else {
/* NOTE: no subtype */
get_mac_addr(mac);
pp_sprintf(buf,
"%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3],
mac[4], mac[5]);
tlv_len = 17;
strncpy((char *)(lldpdu + lldpdu_len + LLDP_HEADER),
(char *)buf, tlv_len);
}
/* header */ /* header */
lldp_header_tlv(tlv_type); lldp_header_tlv(tlv_type, tlv_len);
/* TLV Info srting */
/* TODO get host system name from wr-core outer world */
strcpy(lldpdu + lldpdu_len, "WR PTP Core");
break; break;
}
case SYS_DESCR: case SYS_DESCR:
/* header */ tlv_len = 0; /* will be calculated later */
lldp_header_tlv(tlv_type); uint8_t *pdu_p;
/* set the pointer after TLV's header */
pdu_p = &lldpdu[lldpdu_len + LLDP_HEADER];
/* TLV Info srting */ /* TLV Info srting */
strcpy(lldpdu + lldpdu_len, build_revision); strncpy((char *)(pdu_p), wrc_hw_name,
HW_NAME_LENGTH - 1);
pdu_p += strnlen(wrc_hw_name, HW_NAME_LENGTH - 1);
strcpy((char *)(pdu_p), ": ");
pdu_p += 2; /* length of ": " */
strncpy((char *)(pdu_p), build_revision, 32);
pdu_p += strnlen(build_revision, 32);
tlv_len =
(uint8_t)(pdu_p - &lldpdu[lldpdu_len + LLDP_HEADER]);
lldp_header_tlv(tlv_type, tlv_len);
break; break;
case SYS_CAPLTY: case SYS_CAPLTY:
/* don't implement this, this TLV is optional */
break;
tlv_len = 4;
/* header */ /* header */
lldp_header_tlv(tlv_type); lldp_header_tlv(tlv_type, tlv_len);
/* TLV Info string */ /* TLV Info string */
memset(lldpdu + lldpdu_len, 0x0, 4); memset(lldpdu + lldpdu_len, 0x0, tlv_len);
break; break;
case MNG_ADD: case MNG_ADD:
/* TODO: fill with MAC if no IP present */
if (!HAS_IP || !memcmp(ipWR, "\0\0\0\0", 4)) {
/* if no IP present skip this field */
break;
}
/* TODO: dynamic len */
tlv_len = 0xc;
/* header */ /* header */
lldp_header_tlv(tlv_type); lldp_header_tlv(tlv_type, tlv_len);
/* TLV Info string */ /* TLV Info string */
/* TODO get host system name from wr-core outer world */ lldpdu[lldpdu_len] = MNG_ADDR_LEN; /* len */
lldpdu[lldpdu_len] = 0x5; /* len */ /* mngt add subtype */
lldpdu[lldpdu_len + LLDP_SUBTYPE] = 0x1; /* mngt add subtype */ lldpdu[lldpdu_len + LLDP_SUBTYPE] = MNG_ADDR_SUBTYPE_IPv4;
lldpdu[lldpdu_len + IF_SUBTYPE] = 0x1; /* if subtype */ /* if subtype (ifIndex)*/
lldpdu[lldpdu_len + IF_NUM] = 0x1; /* if number */ lldpdu[lldpdu_len + MNT_IF_SUBTYPE] = MNG_IF_NUM_SUBTYPE_IFINDEX;
/* if number */
lldpdu[lldpdu_len + MNT_IF_NUM] = 0x1;
/* TLV Info srting */ /* TLV Info srting */
if (HAS_IP) { if (HAS_IP) {
getIP(ipWR); getIP(ipWR);
char buf[32]; char buf[32];
format_ip(buf, ipWR);
memcpy(&lldpdu[lldpdu_len + LLDP_SUBTYPE + 1], ipWR,4); format_ip(buf, ipWR);
} memcpy(&lldpdu[lldpdu_len + LLDP_SUBTYPE + 1],
ipWR, 4);
}
/* TODO: add info about VLAN 9.5.9.9g */
break; break;
case USER_DEF: case USER_DEF:
/* TODO define WR TLV */ /* TODO define WR TLV */
...@@ -139,22 +203,21 @@ static void lldp_add_tlv(int tlv_type) { ...@@ -139,22 +203,21 @@ static void lldp_add_tlv(int tlv_type) {
return; return;
break; break;
} }
lldpdu_len += tlv_type_len[tlv_type]; lldpdu_len += tlv_len;
} }
static void lldp_update(void) static void lldp_update(void)
{ {
int i; int i;
/* add mandatory LLDP TLVs */ /* add mandatory LLDP TLVs */
memset(lldpdu, 0x0, LLDP_PKT_LEN); memset(lldpdu, 0x0, LLDP_MAX_PKT_LEN);
lldpdu_len = 0; lldpdu_len = 0;
for (i=CHASSIS_ID; i <= SYS_CAPLTY; i++) pp_printf("lldp update\n");
/* add all TLV's */
for (i = CHASSIS_ID; i <= MNG_ADD; i++)
lldp_add_tlv(i); lldp_add_tlv(i);
/* add optional TLVs */
lldp_add_tlv(MNG_ADD);
/* end TLVs */ /* end TLVs */
lldp_add_tlv(END_LLDP); lldp_add_tlv(END_LLDP);
} }
...@@ -178,19 +241,33 @@ static void lldp_init(void) ...@@ -178,19 +241,33 @@ static void lldp_init(void)
static int lldp_poll(void) static int lldp_poll(void)
{ {
static int ticks; static int ticks;
unsigned char new_ipWR;
static unsigned char old_ipWR;
uint8_t new_mac[ETH_ALEN];
static uint8_t old_mac[ETH_ALEN];
/* periodic tasks */ /* periodic tasks */
if (ticks > LLDP_TX_FQ) { if (ticks > LLDP_TX_TICK_INTERVAL) {
get_mac_addr(new_mac);
if (HAS_IP) {
getIP(&new_ipWR);
}
if (HAS_IP && (ip_status != IP_TRAINING)) { /* Update only when IP or MAC changed */
//lldp_add_tlv(PORT); /* TODO: or VLAN changed */
lldp_add_tlv(MNG_ADD); if (memcmp(&new_mac, &old_mac, ETH_ALEN)
|| (HAS_IP && (ip_status != IP_TRAINING)
&& memcmp(&new_ipWR, &old_ipWR, IPLEN))
) {
/* update LLDP info */
lldp_update(); lldp_update();
/* update other dynamic TLVs */ /* copy new MAC nad IP */
memcpy(&old_mac, &new_mac, ETH_ALEN);
memcpy(&old_ipWR, &new_ipWR, IPLEN);
} }
ptpd_netif_sendto(lldp_socket, &addr, lldpdu, LLDP_PKT_LEN, 0); ptpd_netif_sendto(lldp_socket, &addr, lldpdu, lldpdu_len, 0);
ticks = 0; ticks = 0;
return 1; return 1;
......
...@@ -11,26 +11,41 @@ ...@@ -11,26 +11,41 @@
#ifndef __LLDP_H #ifndef __LLDP_H
#define __LLDP_H #define __LLDP_H
#include "minic.h"
#define LLDP_MCAST_MAC "\x01\x80\xC2\x00\x00\x0E" #define LLDP_MCAST_MAC "\x01\x80\xC2\x00\x00\x0E" /* 802.1AB-2005,
#define LLDP_ETH_TYP 0x88CC Table 8-1 */
#define LLDP_ETH_TYP 0x88CC /* 802.1AB-2005, Table 8-2 */
#define LLDP_PKT_LEN 0x9E /* 158 bytes */
#define TLV_MAX 0xA #define LLDP_MAX_PKT_LEN 0x9E /* 158 bytes */
#define LLDP_HEADER 0x2 #define TLV_MAX 0xA
#define LLDP_SUBTYPE 0x1 #define LLDP_HEADER 0x2
#define IF_SUBTYPE 0x6 #define LLDP_SUBTYPE 0x1
#define IF_NUM 0x10 #define MNT_IF_SUBTYPE 0x6
#define MNT_IF_NUM 10
#define LLDP_ID_SUBTYPE_MAC 3
#define LLDP_TX_TICK_INTERVAL 1000
#define LLDP_TX_FQ 1000
#define CHASSIS_ID_TLV_LEN (1 + ETH_ALEN) /* chassis ID subtype byte
enum TLV_TYPE { END_LLDP = 0, /* mandatory TLVs */ * + MAC Len */
#define CHASSIS_ID_TYPE_MAC 4 /* 802.1AB-2005, table 9-2 */
#define PORT_ID_TLV_LEN (1 + ETH_ALEN) /* port ID subtype byte
* + MAC Len */
#define PORT_ID_SUBTYPE_MAC 3 /* 802.1AB-2005, table 9-3 */
#define TTL_ID_TLV_LEN 2 /* 802.1AB-2005, Figure 9-6 */
#define TTL_BYTE_MSB 0
#define TTL_BYTE_LSB 1
#define PORT_NAME "wr0"
#define IPLEN 4 /* len of IP address in bytes */
#define MNG_ADDR_LEN (1 + IPLEN) /* MNT addr subtype + IPLEN */
#define MNG_ADDR_SUBTYPE_IPv4 1 /* ianaAddressFamilyNumbers MIB */
#define MNG_ADDR_SUBTYPE_MAC 6 /* ianaAddressFamilyNumbers MIB */
#define MNG_IF_NUM_SUBTYPE_IFINDEX 2 /* 802.1AB-2005, 9.5.9.5 */
enum TLV_TYPE {
END_LLDP = 0, /* mandatory TLVs */
CHASSIS_ID, CHASSIS_ID,
PORT_ID, PORT_ID,
TTL, TTL,
PORT, /* optional TLVs */ PORT, /* optional TLVs */
SYS_NAME, SYS_NAME,
SYS_DESCR, SYS_DESCR,
SYS_CAPLTY, SYS_CAPLTY,
...@@ -38,15 +53,4 @@ enum TLV_TYPE { END_LLDP = 0, /* mandatory TLVs */ ...@@ -38,15 +53,4 @@ enum TLV_TYPE { END_LLDP = 0, /* mandatory TLVs */
USER_DEF USER_DEF
}; };
uint16_t tlv_type_len[TLV_MAX] = { 0x0, /* LEN_LLDP_END */
0x7, /* LEN_CHASSIS_ID */
0x7, /* LEN_PORT_ID */
0x2, /* LEN_TTL */
0x14, /* LEN_PORT */
0x14, /* LEN_SYS_NAME */
0x14, /* LEN_SYS_DESCR */
0x4, /* LEN_SYS_CAPLTY */
0xC /* LEN_MNG_ADD */
};
#endif /* __LLDP_H */ #endif /* __LLDP_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment