Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
White Rabbit core collection
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
30
Issues
30
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Schedules
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
White Rabbit core collection
Commits
a9add108
Commit
a9add108
authored
Dec 01, 2017
by
Grzegorz Daniluk
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'adam-lldp-rebased' into proposed_master
parents
0e488977
214464b3
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
241 additions
and
149 deletions
+241
-149
Kconfig
Kconfig
+9
-8
spec_defconfig
configs/spec_defconfig
+1
-0
spec_pdelay_defconfig
configs/spec_pdelay_defconfig
+1
-0
lldp.c
lib/lldp.c
+198
-104
lldp.h
lib/lldp.h
+32
-37
No files found.
Kconfig
View file @
a9add108
...
...
@@ -297,6 +297,15 @@ config ABSCAL
using a loop-back SFP adapter, according to the procedure
described and documented by Peter Jansweijer.
config LLDP
depends on WR_NODE
boolean "Include LLDP protocol transmit-only"
default n
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.
#
# This is a set of configuration options that should not be changed by
# normal users. If the "developer" menu is used, the binary is tainted.
...
...
@@ -576,11 +585,3 @@ 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.
configs/spec_defconfig
View file @
a9add108
...
...
@@ -42,6 +42,7 @@ CONFIG_GENSDBFS=y
CONFIG_WR_DIAG=y
# CONFIG_WR_NODE_SIM is not set
CONFIG_ABSCAL=y
CONFIG_LLDP=y
#
# wrpc-sw is tainted if you change the following options
...
...
configs/spec_pdelay_defconfig
View file @
a9add108
...
...
@@ -42,6 +42,7 @@ CONFIG_GENSDBFS=y
CONFIG_WR_DIAG=y
# CONFIG_WR_NODE_SIM is not set
CONFIG_ABSCAL=y
CONFIG_LLDP=y
#
# wrpc-sw is tainted if you change the following options
...
...
lib/lldp.c
View file @
a9add108
...
...
@@ -2,7 +2,10 @@
* This work is part of the White Rabbit project
*
* Copyright (C) 2011 GSI (www.gsi.de)
* Copyright (C) 2017 CERN
*
* Author: Cesar Prados <c.prados@gsi.de>
* Author: Adam Wujek <adam.wujek@cern.ch>
*
* LLDP transmit-only station
*
...
...
@@ -17,9 +20,10 @@
#include "endpoint.h"
#include "ipv4.h"
#include "shell.h"
#include "syscon.h"
#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
;
/* tx-only socket */
...
...
@@ -31,109 +35,194 @@ static struct wrpc_socket __static_lldp_socket = {
static
struct
wrpc_socket
*
lldp_socket
;
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
];
lldpdu
[
lldpdu_len
]
=
tlv_type
*
2
;
lldpdu
[
lldpdu_len
+
LLDP_SUBTYPE
]
=
tlv_type_len
[
tlv_type
];
static
void
lldp_header_tlv
(
uint8_t
tlv_type
,
uint8_t
tlv_len
)
{
lldpdu
[
lldpdu_len
]
=
tlv_type
<<
1
;
lldpdu
[
lldpdu_len
+
LLDP_SUBTYPE
]
=
tlv_len
;
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
)
{
u
nsigned
char
mac
[
6
];
u
int8_t
mac
[
6
];
unsigned
char
ipWR
[
4
];
switch
(
tlv_type
)
{
case
END_LLDP
:
/* header */
lldp_header_tlv
(
tlv_type
);
/* End TLV */
memcpy
(
lldpdu
+
lldpdu_len
,
0x0
,
tlv_type_len
[
tlv_type
]);
break
;
case
CHASSIS_ID
:
/* header */
lldp_header_tlv
(
tlv_type
);
/* TLV Chassis Component */
lldpdu
[
lldpdu_len
]
=
4
;
int
tlv_len
=
0
;
switch
(
tlv_type
)
{
case
END_LLDP
:
/* End TLV */
/* header */
lldp_header_tlv
(
tlv_type
,
tlv_len
);
break
;
case
CHASSIS_ID
:
tlv_len
=
CHASSIS_ID_TLV_LEN
;
/* header */
lldp_header_tlv
(
tlv_type
,
tlv_len
);
/* TLV Chassis Component */
fill_mac
(
&
lldpdu
[
lldpdu_len
],
CHASSIS_ID_TYPE_MAC
);
break
;
case
PORT_ID
:
tlv_len
=
PORT_ID_TLV_LEN
;
/* header */
lldp_header_tlv
(
tlv_type
,
tlv_len
);
/* TLV portID */
fill_mac
(
&
lldpdu
[
lldpdu_len
],
PORT_ID_SUBTYPE_MAC
);
break
;
case
TTL
:
tlv_len
=
TTL_ID_TLV_LEN
;
/* header */
lldp_header_tlv
(
tlv_type
,
tlv_len
);
/* TLV Time to Live */
/* 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
;
case
PORT
:
tlv_len
=
strlen
(
PORT_NAME
)
+
1
;
/* header */
lldp_header_tlv
(
tlv_type
,
tlv_len
);
strcpy
((
char
*
)
lldpdu
+
lldpdu_len
,
PORT_NAME
);
break
;
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
);
memcpy
(
lldpdu
+
(
lldpdu_len
+
LLDP_SUBTYPE
),
mac
,
6
);
break
;
case
PORT_ID
:
/* header */
lldp_header_tlv
(
tlv_type
);
/* TLV Interce Alias */
lldpdu
[
lldpdu_len
]
=
7
;
strcpy
(
lldpdu
+
(
lldpdu_len
+
LLDP_SUBTYPE
),
"WR Port"
);
break
;
case
TTL
:
/* header */
lldp_header_tlv
(
tlv_type
);
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 */
lldp_header_tlv
(
tlv_type
,
tlv_len
);
/* TLV Time to Live */
lldpdu
[
lldpdu_len
+
LLDP_SUBTYPE
]
=
0x20
;
/* sec */
break
;
case
PORT
:
/* header */
lldp_header_tlv
(
tlv_type
);
/* TLV Info srting */
if
(
HAS_IP
)
{
getIP
(
ipWR
);
char
buf
[
32
];
format_ip
(
buf
,
ipWR
);
strcpy
(
lldpdu
+
lldpdu_len
,
buf
);
}
break
;
}
case
SYS_DESCR
:
tlv_len
=
0
;
/* will be calculated later */
uint8_t
*
pdu_p
;
/* set the pointer after TLV's header */
pdu_p
=
&
lldpdu
[
lldpdu_len
+
LLDP_HEADER
];
/* TLV Info srting */
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
;
case
SYS_CAPLTY
:
/* don't implement this, this TLV is optional */
break
;
tlv_len
=
4
;
/* header */
lldp_header_tlv
(
tlv_type
,
tlv_len
);
/* TLV Info string */
memset
(
lldpdu
+
lldpdu_len
,
0x0
,
tlv_len
);
break
;
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
;
case
SYS_NAME
:
/* header */
lldp_header_tlv
(
tlv_type
);
/* TLV Info srting */
/* TODO get host system name from wr-core outer world */
strcpy
(
lldpdu
+
lldpdu_len
,
"WR PTP Core"
);
}
/* TODO: dynamic len */
tlv_len
=
0xc
;
/* header */
lldp_header_tlv
(
tlv_type
,
tlv_len
);
/* TLV Info string */
lldpdu
[
lldpdu_len
]
=
MNG_ADDR_LEN
;
/* len */
/* mngt add subtype */
lldpdu
[
lldpdu_len
+
LLDP_SUBTYPE
]
=
MNG_ADDR_SUBTYPE_IPv4
;
/* if subtype (ifIndex)*/
lldpdu
[
lldpdu_len
+
MNT_IF_SUBTYPE
]
=
MNG_IF_NUM_SUBTYPE_IFINDEX
;
/* if number */
lldpdu
[
lldpdu_len
+
MNT_IF_NUM
]
=
0x1
;
/* TLV Info srting */
if
(
HAS_IP
)
{
getIP
(
ipWR
);
char
buf
[
32
];
format_ip
(
buf
,
ipWR
);
memcpy
(
&
lldpdu
[
lldpdu_len
+
LLDP_SUBTYPE
+
1
],
ipWR
,
4
);
}
/* TODO: add info about VLAN 9.5.9.9g */
break
;
case
USER_DEF
:
/* TODO define WR TLV */
return
;
break
;
default:
return
;
break
;
}
lldpdu_len
+=
tlv_len
;
}
break
;
case
SYS_DESCR
:
/* header */
lldp_header_tlv
(
tlv_type
);
static
void
lldp_update
(
void
)
{
int
i
;
/* add mandatory LLDP TLVs */
memset
(
lldpdu
,
0x0
,
LLDP_MAX_PKT_LEN
);
lldpdu_len
=
0
;
/* TLV Info srting */
strcpy
(
lldpdu
+
lldpdu_len
,
build_revision
);
break
;
case
SYS_CAPLTY
:
/* header */
lldp_header_tlv
(
tlv_type
);
pp_printf
(
"lldp update
\n
"
);
/* add all TLV's */
for
(
i
=
CHASSIS_ID
;
i
<=
MNG_ADD
;
i
++
)
lldp_add_tlv
(
i
);
/* TLV Info string */
memset
(
lldpdu
+
lldpdu_len
,
0x0
,
4
);
break
;
case
MNG_ADD
:
/* header */
lldp_header_tlv
(
tlv_type
);
/* TLV Info string */
/* TODO get host system name from wr-core outer world */
lldpdu
[
lldpdu_len
]
=
0x4
;
/* len */
lldpdu
[
lldpdu_len
+
LLDP_SUBTYPE
]
=
0x1
;
/* mngt add subtype */
lldpdu
[
lldpdu_len
+
IF_SUBTYPE
]
=
0x1
;
/* if subtype */
lldpdu
[
lldpdu_len
+
IF_NUM
]
=
0x1
;
/* if number */
break
;
case
USER_DEF
:
/* TODO define WR TLV */
break
;
default:
break
;
}
/* end TLVs */
lldp_add_tlv
(
END_LLDP
);
}
static
void
lldp_init
(
void
)
{
struct
wr_sockaddr
saddr
;
int
i
;
/* LLDP: raw ethernet*/
memset
(
&
saddr
,
0x0
,
sizeof
(
saddr
));
...
...
@@ -145,33 +234,38 @@ static void lldp_init(void)
memset
(
&
addr
,
0x0
,
sizeof
(
struct
wr_sockaddr
));
memcpy
(
addr
.
mac
,
LLDP_MCAST_MAC
,
6
);
/* add mandatory LLDP TLVs */
memset
(
lldpdu
,
0x0
,
LLDP_PKT_LEN
);
lldpdu_len
=
0
;
for
(
i
=
CHASSIS_ID
;
i
<=
SYS_CAPLTY
;
i
++
)
lldp_add_tlv
(
i
);
/* add optional TLVs */
lldp_add_tlv
(
MNG_ADD
);
/* end TLVs */
lldp_add_tlv
(
END_LLDP
);
lldp_update
();
}
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 */
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
))
{
lldp_add_tlv
(
PORT
);
/* update other dynamic TLVs */
/* Update only when IP or MAC changed */
/* TODO: or VLAN changed */
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
();
/* 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
;
return
1
;
...
...
lib/lldp.h
View file @
a9add108
...
...
@@ -11,24 +11,41 @@
#ifndef __LLDP_H
#define __LLDP_H
#define LLDP_MCAST_MAC "\x01\x80\xC2\x00\x00\x0E"
#define LLDP_ETH_TYP 0x88CC
#define LLDP_PKT_LEN 0x9E
/* 158 bytes */
#define TLV_MAX 0xA
#define LLDP_HEADER 0x2
#define LLDP_SUBTYPE 0x1
#define IF_SUBTYPE 0x6
#define IF_NUM 0x10
#define LLDP_TX_FQ 1000
enum
TLV_TYPE
{
END_LLDP
=
0
,
/* mandatory TLVs */
#include "minic.h"
#define LLDP_MCAST_MAC "\x01\x80\xC2\x00\x00\x0E"
/* 802.1AB-2005,
Table 8-1 */
#define LLDP_ETH_TYP 0x88CC
/* 802.1AB-2005, Table 8-2 */
#define LLDP_MAX_PKT_LEN 0x9E
/* 158 bytes */
#define TLV_MAX 0xA
#define LLDP_HEADER 0x2
#define LLDP_SUBTYPE 0x1
#define MNT_IF_SUBTYPE 0x6
#define MNT_IF_NUM 10
#define LLDP_TX_TICK_INTERVAL 1000
#define CHASSIS_ID_TLV_LEN (1 + ETH_ALEN)
/* chassis ID subtype byte
* + 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
,
PORT_ID
,
TTL
,
PORT
,
/* optional TLVs */
PORT
,
/* optional TLVs */
SYS_NAME
,
SYS_DESCR
,
SYS_CAPLTY
,
...
...
@@ -36,26 +53,4 @@ enum TLV_TYPE { END_LLDP = 0, /* mandatory TLVs */
USER_DEF
};
uint16_t
tlv_type_len
[
TLV_MAX
]
=
{
0x0
,
/* LEN_LLDP_END */
0x7
,
/* 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 */
0xC
/* LEN_MNG_ADD */
};
uint16_t
tlv_offset
[
TLV_MAX
]
=
{
0x79
,
/* LEN_LLDP_END */
0x0
,
/* LEN_CHASSIS_ID */
0x9
,
/* LEN_PORT_ID */
0x1F
,
/* LEN_TTL */
0x23
,
/* LEN_PORT */
0x39
,
/* LEN_SYS_NAME */
0x4F
,
/* LEN_SYS_DESCR */
0x65
,
/* LEN_SYS_CAPLTY */
0x6B
/* LEN_MNG_ADD */
};
#endif
/* __LLDP_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment