fabricd: support transmission/reception of circuit-scoped LSPs

OpenFabric makes use of flooding scope LSPs to reduce the amount of
reflooding caused by the update process. Implement transmission and
reception of such PDUs.

Signed-off-by: Christian Franke <chris@opensourcerouting.org>
This commit is contained in:
Christian Franke 2018-08-09 22:07:20 +02:00
parent 9b39405f00
commit 1cbd5b37b7
2 changed files with 44 additions and 7 deletions

View File

@ -710,12 +710,35 @@ out:
static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
const uint8_t *ssnpa, uint8_t max_area_addrs) const uint8_t *ssnpa, uint8_t max_area_addrs)
{ {
int level = (pdu_type == L1_LINK_STATE) ? ISIS_LEVEL1 : ISIS_LEVEL2; int level;
bool circuit_scoped;
if (pdu_type == FS_LINK_STATE) {
if (!fabricd)
return ISIS_ERROR;
if (max_area_addrs != L2_CIRCUIT_FLOODING_SCOPE)
return ISIS_ERROR;
level = ISIS_LEVEL2;
circuit_scoped = true;
/* The stream is used verbatim for sending out new LSPDUs.
* So make sure we store it as an L2 LSPDU internally.
* (compare for the reverse in `send_lsp`) */
stream_putc_at(circuit->rcv_stream, 4, L2_LINK_STATE);
stream_putc_at(circuit->rcv_stream, 7, 0);
} else {
if (pdu_type == L1_LINK_STATE)
level = ISIS_LEVEL1;
else
level = ISIS_LEVEL2;
circuit_scoped = false;
}
if (isis->debugs & DEBUG_UPDATE_PACKETS) { if (isis->debugs & DEBUG_UPDATE_PACKETS) {
zlog_debug( zlog_debug(
"ISIS-Upd (%s): Rcvd L%d LSP on %s, cirType %s, cirID %u", "ISIS-Upd (%s): Rcvd %sL%d LSP on %s, cirType %s, cirID %u",
circuit->area->area_tag, level, circuit->area->area_tag,
circuit_scoped ? "Circuit scoped " : "", level,
circuit->interface->name, circuit->interface->name,
circuit_t2string(circuit->is_type), circuit_t2string(circuit->is_type),
circuit->circuit_id); circuit->circuit_id);
@ -907,7 +930,8 @@ dontcheckadj:
lsp_confusion); lsp_confusion);
tlvs = NULL; tlvs = NULL;
/* ii */ /* ii */
lsp_flood(lsp, NULL); if (!circuit_scoped)
lsp_flood(lsp, NULL);
/* v */ /* v */
ISIS_FLAGS_CLEAR_ALL( ISIS_FLAGS_CLEAR_ALL(
lsp->SSNflags); /* FIXME: lsp->SSNflags); /* FIXME:
@ -952,7 +976,8 @@ dontcheckadj:
/* our own LSP -> 7.3.16.4 c) */ /* our own LSP -> 7.3.16.4 c) */
if (comp == LSP_NEWER) { if (comp == LSP_NEWER) {
lsp_inc_seqno(lsp, hdr.seqno); lsp_inc_seqno(lsp, hdr.seqno);
lsp_flood(lsp, NULL); if (!circuit_scoped)
lsp_flood(lsp, NULL);
} else { } else {
isis_tx_queue_add(circuit->tx_queue, isis_tx_queue_add(circuit->tx_queue,
lsp, TX_LSP_NORMAL); lsp, TX_LSP_NORMAL);
@ -1035,7 +1060,8 @@ dontcheckadj:
circuit->area, level, false); circuit->area, level, false);
tlvs = NULL; tlvs = NULL;
} }
lsp_flood(lsp, circuit); if (!circuit_scoped)
lsp_flood(lsp, circuit);
/* iv */ /* iv */
if (circuit->circ_type != CIRCUIT_T_BROADCAST) if (circuit->circ_type != CIRCUIT_T_BROADCAST)
@ -1342,6 +1368,7 @@ static int pdu_size(uint8_t pdu_type, uint8_t *size)
break; break;
case L1_LINK_STATE: case L1_LINK_STATE:
case L2_LINK_STATE: case L2_LINK_STATE:
case FS_LINK_STATE:
*size = ISIS_LSP_HDR_LEN; *size = ISIS_LSP_HDR_LEN;
break; break;
case L1_COMPLETE_SEQ_NUM: case L1_COMPLETE_SEQ_NUM:
@ -1442,7 +1469,9 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
} }
/* either 3 or 0 */ /* either 3 or 0 */
if (max_area_addrs != 0 && max_area_addrs != isis->max_area_addrs) { if (pdu_type != FS_LINK_STATE /* FS PDU doesn't contain max area addr field */
&& max_area_addrs != 0
&& max_area_addrs != isis->max_area_addrs) {
flog_err( flog_err(
ISIS_ERR_PACKET, ISIS_ERR_PACKET,
"maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %" PRIu8 "maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %" PRIu8
@ -1459,6 +1488,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
break; break;
case L1_LINK_STATE: case L1_LINK_STATE:
case L2_LINK_STATE: case L2_LINK_STATE:
case FS_LINK_STATE:
retval = process_lsp(pdu_type, circuit, ssnpa, max_area_addrs); retval = process_lsp(pdu_type, circuit, ssnpa, max_area_addrs);
break; break;
case L1_COMPLETE_SEQ_NUM: case L1_COMPLETE_SEQ_NUM:
@ -2155,6 +2185,11 @@ void send_lsp(void *arg, struct isis_lsp *lsp, enum isis_tx_type tx_type)
/* copy our lsp to the send buffer */ /* copy our lsp to the send buffer */
stream_copy(circuit->snd_stream, lsp->pdu); stream_copy(circuit->snd_stream, lsp->pdu);
if (tx_type == TX_LSP_CIRCUIT_SCOPED) {
stream_putc_at(circuit->snd_stream, 4, FS_LINK_STATE);
stream_putc_at(circuit->snd_stream, 7, L2_CIRCUIT_FLOODING_SCOPE);
}
if (isis->debugs & DEBUG_UPDATE_PACKETS) { if (isis->debugs & DEBUG_UPDATE_PACKETS) {
zlog_debug("ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08" PRIx32 zlog_debug("ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08" PRIx32
", cksum 0x%04" PRIx16 ", lifetime %" PRIu16 ", cksum 0x%04" PRIx16 ", lifetime %" PRIu16

View File

@ -127,6 +127,8 @@ struct isis_p2p_hello_hdr {
#define L1_LINK_STATE 18 #define L1_LINK_STATE 18
#define L2_LINK_STATE 20 #define L2_LINK_STATE 20
#define FS_LINK_STATE 10
#define L2_CIRCUIT_FLOODING_SCOPE 2
struct isis_lsp_hdr { struct isis_lsp_hdr {
uint16_t pdu_len; uint16_t pdu_len;
uint16_t rem_lifetime; uint16_t rem_lifetime;