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,
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) {
zlog_debug(
"ISIS-Upd (%s): Rcvd L%d LSP on %s, cirType %s, cirID %u",
circuit->area->area_tag, level,
"ISIS-Upd (%s): Rcvd %sL%d LSP on %s, cirType %s, cirID %u",
circuit->area->area_tag,
circuit_scoped ? "Circuit scoped " : "", level,
circuit->interface->name,
circuit_t2string(circuit->is_type),
circuit->circuit_id);
@ -907,7 +930,8 @@ dontcheckadj:
lsp_confusion);
tlvs = NULL;
/* ii */
lsp_flood(lsp, NULL);
if (!circuit_scoped)
lsp_flood(lsp, NULL);
/* v */
ISIS_FLAGS_CLEAR_ALL(
lsp->SSNflags); /* FIXME:
@ -952,7 +976,8 @@ dontcheckadj:
/* our own LSP -> 7.3.16.4 c) */
if (comp == LSP_NEWER) {
lsp_inc_seqno(lsp, hdr.seqno);
lsp_flood(lsp, NULL);
if (!circuit_scoped)
lsp_flood(lsp, NULL);
} else {
isis_tx_queue_add(circuit->tx_queue,
lsp, TX_LSP_NORMAL);
@ -1035,7 +1060,8 @@ dontcheckadj:
circuit->area, level, false);
tlvs = NULL;
}
lsp_flood(lsp, circuit);
if (!circuit_scoped)
lsp_flood(lsp, circuit);
/* iv */
if (circuit->circ_type != CIRCUIT_T_BROADCAST)
@ -1342,6 +1368,7 @@ static int pdu_size(uint8_t pdu_type, uint8_t *size)
break;
case L1_LINK_STATE:
case L2_LINK_STATE:
case FS_LINK_STATE:
*size = ISIS_LSP_HDR_LEN;
break;
case L1_COMPLETE_SEQ_NUM:
@ -1442,7 +1469,9 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
}
/* 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(
ISIS_ERR_PACKET,
"maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %" PRIu8
@ -1459,6 +1488,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
break;
case L1_LINK_STATE:
case L2_LINK_STATE:
case FS_LINK_STATE:
retval = process_lsp(pdu_type, circuit, ssnpa, max_area_addrs);
break;
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 */
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) {
zlog_debug("ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08" PRIx32
", cksum 0x%04" PRIx16 ", lifetime %" PRIu16

View File

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