Commit ca16dbfb authored by Cesar Prados's avatar Cesar Prados Committed by Grzegorz Daniluk

lldp: add LLDP support as transmit-only node

LLDP a vendor-neutral link layer protocol used by network devices
for advertising their identity, capabilities, and neighbors.
Implements a transmit-only nodes, the node only transmit periodically
and doesn't process any LLDPUD.
parent eae94a74
......@@ -554,3 +554,11 @@ config PPSI
boolean
help
Select this option for the ppsi engine (now only option)
config LLDP
depends on DEVELOPER
boolean "Include LLDP protocol transmit-only"
help
This enable LLDP support. LLDP is a vendor-neutral link layer protocol
used by network devices for advertising their identity, capabilities,
and neighbors on local area network.
......@@ -11,3 +11,4 @@ obj-$(CONFIG_IP) += lib/ipv4.o lib/arp.o lib/icmp.o lib/udp.o lib/bootp.o
obj-$(CONFIG_SYSLOG) += lib/syslog.o
obj-$(CONFIG_LATENCY_PROBE) += lib/latency.o
obj-$(CONFIG_SNMP) += lib/snmp.o
obj-$(CONFIG_LLDP) += lib/lldp.o
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2011 GSI (www.gsi.de)
* Author: Cesar Prados <c.prados@gsi.de>
*
* LLDP transmit-only station
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#include <string.h>
#include "endpoint.h"
#include "ipv4.h"
#include "ptpd_netif.h"
#include "lldp.h"
#ifndef htons
#define htons(x) x
#endif
static char lldpdu[LLDP_PKT_LEN];
static uint16_t lldpdu_len;
/* LLDPC: a tx-only socket */
static struct wrpc_socket __static_lldp_socket = {
.queue.buff = NULL,
.queue.size = 0,
};
static struct wrpc_socket *lldp_socket;
static void lldp_header_tlv(int tlv_type) {
lldpdu[lldpdu_len] = tlv_type * 2;
lldpdu[lldpdu_len + 1] = tlv_type_len[tlv_type];
lldpdu_len += LLDP_HEADER;
}
static void lldp_add_tlv(int tlv_type) {
switch(tlv_type) {
case END_LLDP:
break;
case CHASSIS_ID:
/* header */
lldp_header_tlv(tlv_type);
/* TLV Info srting */
lldpdu[lldpdu_len] = 1; /* Chassis Component */
strcpy(lldpdu+(lldpdu_len + LLDP_SUBTYPE), "WR Timing Receiver");
lldpdu_len += tlv_type_len[tlv_type];
break;
case PORT_ID:
/* header */
lldp_header_tlv(tlv_type);
/* TLV Info string */
lldpdu[lldpdu_len] = 3; /* Interface Alias */
memcpy(lldpdu+(lldpdu_len + LLDP_SUBTYPE), LLDP_MCAST_MAC, 6);
lldpdu_len += tlv_type_len[tlv_type];
break;
case TTL:
/* header */
lldp_header_tlv(tlv_type);
/* TLV Info srting */
lldpdu[lldpdu_len] = 0x30; /* Interface Alias */
lldpdu_len += tlv_type_len[tlv_type];
break;
case PORT:
/* header */
lldp_header_tlv(tlv_type);
/* TLV Info srting */
strcpy(lldpdu+lldpdu_len, "wr0");
lldpdu_len += tlv_type_len[tlv_type];
break;
case SYS_NAME:
/* header */
lldp_header_tlv(tlv_type);
/* TLV Info srting */
strcpy(lldpdu+lldpdu_len, "WR Timing Receiver");
lldpdu_len += tlv_type_len[tlv_type];
break;
case SYS_DESCR:
/* header */
lldp_header_tlv(tlv_type);
/* TLV Info srting */
strcpy(lldpdu+lldpdu_len, "Firmware Commit/Version");
lldpdu_len += tlv_type_len[tlv_type];
break;
case SYS_CAPLTY:
/* header */
lldp_header_tlv(tlv_type);
/* TLV Info string */
lldpdu[lldpdu_len] = 7; /* Station Only */
lldpdu_len += tlv_type_len[tlv_type];
break;
case MNG_ADD:
/* to be added */
break;
default:
break;
}
}
static void lldp_init(void)
{
struct wr_sockaddr saddr;
int i;
/* LLDP: raw ethernet*/
memset(&saddr, 0, sizeof(saddr));
saddr.ethertype = htons(0x88CC);
lldp_socket = ptpd_netif_create_socket(&__static_lldp_socket, &saddr,
PTPD_SOCK_RAW_ETHERNET, 0);
memset(lldpdu,0x0,500);
lldpdu_len = 0;
/* Create LLDP TLVs */
for (i=CHASSIS_ID; i <= SYS_CAPLTY; i++)
lldp_add_tlv(i);
}
static void lldp_poll(void)
{
uint8_t buf[LLDP_PKT_LEN];
struct wr_sockaddr addr;
static int tick;
memset(&addr, 0x0, sizeof(struct wr_sockaddr));
memcpy(addr.mac, LLDP_MCAST_MAC, 6);
memset(buf, 0x0, LLDP_PKT_LEN);
memcpy(buf, lldpdu, LLDP_PKT_LEN);
if (tick > 10000) { /* to be fixed, waiting for periodic tasks */
ptpd_netif_sendto(lldp_socket, &addr, buf, LLDP_PKT_LEN, 0);
tick = 0;
}
else
tick += 1;
}
DEFINE_WRC_TASK(lldp) = {
.name = "lldp",
.init = lldp_init,
.job = lldp_poll,
};
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2011 GSI (www.gsi.de)
* Author: Cesar Prados <c.prados@gsi.de>
*
* LLDP transmit-only station
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#ifndef __LLDP_H
#define __LLDP_H
#define LLDP_MCAST_MAC "\x01\x80\xC2\x00\x00\x0E"
#define LLDP_PKT_LEN 0x9E /* 158 bytes */
#define TLV_MAX 0x9
#define LLDP_HEADER 0x2
#define LLDP_SUBTYPE 0x1
enum TLV_TYPE { END_LLDP = 0, /* mandatory TLVs */
CHASSIS_ID,
PORT_ID,
TTL,
PORT, /* optional TLVs */
SYS_NAME,
SYS_DESCR,
SYS_CAPLTY,
MNG_ADD
};
uint16_t tlv_type_len[TLV_MAX] = { 0x0, /* LEN_LLDP_END */
0x14, /* LEN_CHASSIS_ID */
0x14, /* LEN_PORT_ID */
0x2, /* LEN_TTL */
0x14, /* LEN_PORT */
0x14, /* LEN_SYS_NAME */
0x14, /* LEN_SYS_DESCR */
0x4, /* LEN_SYS_CAPLTY */
0x1E /* LEN_MNG_ADD */
};
#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