Skip to content

Commit

Permalink
Implement IEC61375-2-5 TTDP HELLO linkwatcher and runner.
Browse files Browse the repository at this point in the history
+1)
    Add support to supply a file which holds a list of possible topocounts. The
    file shall contain one topocount value on each row and stored as hexadecimal,
    i.e.:
       11223344
       aabbccdd
    The topocount values in this list contains valid topocounts for which will
    be used in recovery mode to let a ETBN join the backbone again if it
    previously was lost.

+2)
    If a node has lengthening set from previously, and no longer has a neighbor,
    it should clear the local lengthening flag in all cases. Previosuly, this
    only happened if the node initially had a null neighbor; this change fixes
    the behavior so that the flag is also correctly cleared for nodes that ended
    up in a combined shortening+lengthening state.

+3)
    Previously, we could sometimes not consider ourselves an end node,
    even when we ought to, if we were quick enough to lose our neighbor
    before the higher layers of the stack could notify us that we're no
    longer receiving TOPOLOGY frames.

    After this fix, we consider ourselves as an intermediate node only if
    we both have a non-null neighbor (i.e. HELLO link status is up) and
    we're recieving TOPOLOGY frames, as notified by the higher stack.

+4)
    In order to enable non-inhibited lengthening to work, we need the
    teams at the end of the non-inhibited train to detect that the remote
    train composition has inhibition set. Thus, this change removes the
    requirement that we only cared about remote inhibition if we has
    inhibit set on our end as well (the team was in a FIXED state). This
    is no longer the case - we now only care that we're not in the
    FIXED-MIDDLE state, as that makes no sense for remote inhibition.

+5)
    We now detect whether TOPOLOGY frames are being received in the HELLO
    layer, by use of a parasite socket that listens for the frames directly
    in the teamd runner. Related functionality has been removed from topod.

+6)
    With these changes, the user can now choose how the etbInhibit field in
    the ECSP_STATUS TRDP telegram behaves. The user makes his decision via
    the CLI, in the TTDP configuration context.

    The following options are available:
    * 0: Normal behaviour. As specified in IEC61375-2-3 Annex E:
         0 n/a
         1 inhibit not requested on ETB
         2 inhibit set on local ETBN
         3 inhibit set on remote ETBN
         4 inhibit set on local and remote ETBN
         "Remote ETBN" only considers ETBNs in the local train composition.
         This is the default.
    * 1: As mode 0, but "remote ETBN" now means "non-local ETBN in the
         local, or the remote, train composition".
    * 2: Bitfield mode. The etbInhibit field is now a bitmask
         containing the following bits:
         1 local ETBN
         2 remote ETBN in local train composition
         4 remote ETBN in remote train composition
    * 3: As mode 0, but "ETBN" now means "train composition".

    The motivation behind this is that the current description of the
    etbInhibit field is quite unclear, and that there is currently no way
    for an end user (or TCMS implementation) to read the "remote inhibition"
    flag if one does not have access to the raw TOPOLOGY frames. In certain
    real world use cases, having this information would be of benefit, so we
    now make it possible to adjust the behaviour of this field so as to make
    the information accessible.

+7)
    Add SNMP subagent (teamdagentd)

Co-authored-by:	Jonas Johansson <[email protected]>
Co-authored-by: Magnus Malm <[email protected]>
Co-authored-by: Johan Askerin <[email protected]>
Co-authored-by: Leif Enblom <[email protected]>
Co-authored-by: Jacques de Laval <[email protected]>

Signed-off-by: Andy Koszela <[email protected]>
Signed-off-by: Jonas Johansson <[email protected]>
Signed-off-by: Magnus Malm <[email protected]>
Signed-off-by: Johan Askerin <[email protected]>
Signed-off-by: Leif Enblom <[email protected]>
Signed-off-by: Jacques de Laval <[email protected]>
  • Loading branch information
anleko authored and Mika Juvonen committed Oct 11, 2021
1 parent 5b70f28 commit d65193f
Show file tree
Hide file tree
Showing 23 changed files with 7,524 additions and 11 deletions.
218 changes: 218 additions & 0 deletions doc/iec61375-hello.bpf
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
ld [2] ; check dest. MAC and other Ethernet stuff */
jneq #0xc200000e, drop */
ldh [0]
jneq #0x0180, drop
ld vlan_avail
jneq #1, drop
ld vlan_tci
and #0x0FFF
jneq #0x01EC, drop
ldh [12]
jneq #0x88CC, drop
ld poff ; have M[0] hold the last ok header start position
tax
ld len
sub x
sub #2 ; size of the first TLV header
st M[0]
ld #0x0e ; the first TLV header starts here
ldx #0x0
st M[1] ; this snippet tests whether we'd
stx M[2] ; jump out of bounds, i.e. if
ld M[0] ; ((accumulated TLV sizes in x) -
ldx M[1] ; (packet payload size)) < 0
sub x
jset #0x80000000, drop
ld M[1]
ldx M[2]
tax
ldh [x + 0] ; test one TLV - load TLV header
and #0xFE00 ; extract type
jeq #0x0000, drop ; type 0 is EOF TLV
jneq #0xFE00, skip_tlv_1 ; skip if not HELLO
ldh [x + 0] ; reload TLV header
and #0x01FF ; extract length
jeq #0x56, okay ; must be 86
skip_tlv_1: ldh [x + 0] ; reload TLV header
and #0x01FF ; extract length
add #2 ; header length not included
add x ; previous header offset
st M[1]
stx M[2]
ld M[0]
ldx M[1]
sub x
jset #0x80000000, drop
ld M[1]
ldx M[2]
tax
ldh [x + 0] ; test next TLV... etc
and #0xFE00
jeq #0x0000, drop
jneq #0xFE00, skip_tlv_2
ldh [x + 0]
and #0x01FF
jeq #0x56, okay
skip_tlv_2: ldh [x + 0]
and #0x01FF
add #2
add x
st M[1]
stx M[2]
ld M[0]
ldx M[1]
sub x
jset #0x80000000, drop
ld M[1]
ldx M[2]
tax
ldh [x + 0]
and #0xFE00
jeq #0x0000, drop
jneq #0xFE00, skip_tlv_3
ldh [x + 0]
and #0x01FF
jeq #0x56, okay
skip_tlv_3: ldh [x + 0]
and #0x01FF
add #2
add x
st M[1]
stx M[2]
ld M[0]
ldx M[1]
sub x
jset #0x80000000, drop
ld M[1]
ldx M[2]
tax
ldh [x + 0]
and #0xFE00
jeq #0x0000, drop
jneq #0xFE00, skip_tlv_4
ldh [x + 0]
and #0x01FF
jeq #0x56, okay
skip_tlv_4: ldh [x + 0]
and #0x01FF
add #2
add x
st M[1]
stx M[2]
ld M[0]
ldx M[1]
sub x
jset #0x80000000, drop
ld M[1]
ldx M[2]
tax
ldh [x + 0]
and #0xFE00
jeq #0x0000, drop
jneq #0xFE00, skip_tlv_5
ldh [x + 0]
and #0x01FF
jeq #0x56, okay
skip_tlv_5: ldh [x + 0]
and #0x01FF
add #2
add x
st M[1]
stx M[2]
ld M[0]
ldx M[1]
sub x
jset #0x80000000, drop
ld M[1]
ldx M[2]
tax
ldh [x + 0]
and #0xFE00
jeq #0x0000, drop
jneq #0xFE00, skip_tlv_6
ldh [x + 0]
and #0x01FF
jeq #0x56, okay
skip_tlv_6: ldh [x + 0]
and #0x01FF
add #2
add x
st M[1]
stx M[2]
ld M[0]
ldx M[1]
sub x
jset #0x80000000, drop
ld M[1]
ldx M[2]
tax
ldh [x + 0]
and #0xFE00
jeq #0x0000, drop
jneq #0xFE00, skip_tlv_7
ldh [x + 0]
and #0x01FF
jeq #0x56, okay
skip_tlv_7: ldh [x + 0]
and #0x01FF
add #2
add x
st M[1]
stx M[2]
ld M[0]
ldx M[1]
sub x
jset #0x80000000, drop
ld M[1]
ldx M[2]
tax
ldh [x + 0]
and #0xFE00
jeq #0x0000, drop
jneq #0xFE00, skip_tlv_8
ldh [x + 0]
and #0x01FF
jeq #0x56, okay
skip_tlv_8: ldh [x + 0]
and #0x01FF
add #2
add x
st M[1]
stx M[2]
ld M[0]
ldx M[1]
sub x
jset #0x80000000, drop
ld M[1]
ldx M[2]
tax
ldh [x + 0]
and #0xFE00
jeq #0x0000, drop
jneq #0xFE00, skip_tlv_9
ldh [x + 0]
and #0x01FF
jeq #0x56, okay
skip_tlv_9: ldh [x + 0]
and #0x01FF
add #2
add x
st M[1]
stx M[2]
ld M[0]
ldx M[1]
sub x
jset #0x80000000, drop
ld M[1]
ldx M[2]
tax
ldh [x + 0]
and #0xFE00
jeq #0x0000, drop
jneq #0xFE00, drop
ldh [x + 0]
and #0x01FF
jeq #0x56, okay
jmp drop
okay: ret #-1 ; accept entire packet
drop: ret #0 ; accept nothing
3 changes: 3 additions & 0 deletions include/team.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ bool team_is_our_port(struct team_handle *th, uint32_t port_ifindex);
int team_carrier_set(struct team_handle *th, bool carrier_up);
int team_carrier_get(struct team_handle *th, bool *carrier_up);
int team_link_set(struct team_handle *th, int ifindex, bool link_up);
/*
int team_link_state_set(struct team_handle *th, int ifindex, int new_state);
*/
int team_hwaddr_set(struct team_handle *th, uint32_t ifindex,
const char *addr, unsigned int addr_len);
int team_hwaddr_get(struct team_handle *th, uint32_t ifindex,
Expand Down
9 changes: 6 additions & 3 deletions libteam/ifinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,11 +327,13 @@ int ifinfo_event_handler(struct nl_msg *msg, void *arg)
switch (nlmsg_hdr(msg)->nlmsg_type) {
case RTM_NEWLINK:
if (nl_msg_parse(msg, &event_handler_obj_input_newlink, th) < 0)
err(th, "Unknown message type.");
// err(th, "Unknown message type.");
;
break;
case RTM_DELLINK:
if (nl_msg_parse(msg, &event_handler_obj_input_dellink, th) < 0)
err(th, "Unknown message type.");
// err(th, "Unknown message type.");
;
break;
default:
return NL_OK;
Expand All @@ -358,7 +360,8 @@ static int valid_handler(struct nl_msg *msg, void *arg)
return NL_OK;

if (nl_msg_parse(msg, &valid_handler_obj_input_newlink, th) < 0)
err(th, "Unknown message type.");
// err(th, "Unknown message type.");
;
return NL_OK;
}

Expand Down
53 changes: 53 additions & 0 deletions libteam/libteam.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@
#include <sys/epoll.h>
#include <time.h>
#include <netlink/netlink.h>
#include <netlink/route/link/bridge.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <netlink/cli/utils.h>
#include <netlink/cli/link.h>
#include <linux/if_team.h>
#include <linux/types.h>
#include <linux/filter.h>
#include <linux/genetlink.h>
#include <team.h>
#include <private/list.h>
#include <private/misc.h>
Expand Down Expand Up @@ -1712,8 +1714,59 @@ int team_link_set(struct team_handle *th, int ifindex, bool link_up)
return -EOPNOTSUPP;
#endif
}
/*
TEAM_EXPORT
int team_link_state_set(struct team_handle *th, int ifindex, int new_state) {
#ifdef HAVE_RTNL_LINK_SET_CARRIER
int err = 0;
char ifname[16];
struct nl_sock *sk;
struct nl_cache *brcache;
struct rtnl_link *link;
team_ifindex2ifname(th, ifindex, ifname, 16);
sk = nl_socket_alloc();
if (!sk)
return -ENOMEM;
err = nl_connect(sk, NETLINK_ROUTE);
if (err)
goto free_sock;
err = rtnl_link_alloc_cache(sk, AF_BRIDGE, &brcache);
if (err)
goto free_sock;
link = rtnl_link_get_by_name(brcache, ifname);
if (!link) {
err = -NLE_NODEV;
goto free_cache;
}
rtnl_link_bridge_set_port_state(link, new_state);
err = rtnl_link_change(sk, link, link, NLM_F_REPLACE);
info(th, "...result %d", err);
err = -nl2syserr(err);
rtnl_link_put(link);
free_cache:
nl_cache_free(brcache);
free_sock:
nl_socket_free(sk);
if (err)
warn(th, "NETLINK: could not set state %d on %s", new_state, ifname);
return err;
#else
return -EOPNOTSUPP;
#endif
}
*/
/**
* @param th libteam library context
* @param ifindex interface index
Expand Down
Loading

0 comments on commit d65193f

Please sign in to comment.