mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-28 17:42:20 +00:00
OSPFD: Add Experimental Segment Routing support
This is an implementation of draft-ietf-ospf-segment-routing-extensions-24 and RFC7684 for Extended Link & Prefix Opaque LSA. Look to doc/OSPF_SR.rst for implementation details & known limitations. New files: - ospfd/ospf_sr.h: Segment Routing structure definition (SubTLVs + SRDB) - ospfd/ospf_sr.c: Main functions for Segment Routing support - ospfd/ospf_ext.h: TLVs and SubTLVs definition for RFC7684 - ospfd/ospf_ext.c: RFC7684 Extended Link / Prefix implementation - doc/OSPF-SRr.rst: Documentation Modified Files: - doc/ospfd.texi: Add new Segment Routing CLI command definition - lib/command.h: Add new string command for Segment Routing CLI - lib/mpls.h: Add default value for SRGB - lib/route_types.txt: Add new OSPF Segment Routing route type - ospfd/ospf_dump.[c,h]: Add OSPF SR debug - ospfd/ospf_memory.[c,h]: Add new Segment Routing memory type - ospfd/ospf_opaque.[c,h]: Add ospf_sr_init() starting function - ospfd/ospf_ri.c: Add new functions to Set/Get Segment Routing TLVs Add new ospf_router_info_lsa_upadte() to send Opaque LSA to ospf_sr.c() - ospfd/ospf_ri.h: Add new Router Information SR SubTLVs - ospfd/ospf_spf.c: Add new scheduler when running SPF to trigger update of NHLFE - ospfd/ospfd.h: Add new thread for Segment Routing scheduler - ospfd/subdir.am: Add new files - vtysh/Makefile.am: Add new ospf_sr.c file for vtysh - zebra/kernel_netlink.c: Add new OSPF_SR route type - zebra/rt_netlink.[c,h]: Add new OSPF_SR route type - zebra/zebra_mpls.h: Add new OSPF_SR route type Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
This commit is contained in:
parent
b782607f7f
commit
cf9b9f77f6
82
doc/OSPF-SR.rst
Normal file
82
doc/OSPF-SR.rst
Normal file
@ -0,0 +1,82 @@
|
||||
OSPF Segment Routing
|
||||
====================
|
||||
|
||||
This is an EXPERIMENTAL support of draft draft-ietf-ospf-segment-routing-extensions-24.
|
||||
DON'T use it for production network.
|
||||
|
||||
Implementation details
|
||||
----------------------
|
||||
|
||||
Segment Routing used 3 differents OPAQUE LSA in OSPF to carry the various information:
|
||||
- Router Information: flood the Segment Routing capabilities of the node. This include
|
||||
the supported algorithms, the Segment Routing Global Block (SRGB) and the Maximum Stack
|
||||
Depth.
|
||||
- Extended Link: flood the Adjaceny and Lan Adjacency Segment Identifier
|
||||
- Extended Prefix: flood the Prefix Segment Identifier
|
||||
|
||||
The implementation follow previous TE and Router Information code. It used the OPAQUE LSA
|
||||
functions define in ospf_opaque.[c,h] as well as the OSPF API. This latter is mandatory
|
||||
for the implementation as it provides the Callback to Segment Routing functions (see below)
|
||||
when an Extended Link / Prefix or Router Information is received.
|
||||
|
||||
Following files where modified or added:
|
||||
- ospd_ri.[c,h] have been modified to add the new TLVs for Segment Routing.
|
||||
- ospf_ext.[c,h] implement RFC7684 as base support of Extended Link and Prefix Opaque LSA.
|
||||
- ospf_sr.[c,h] implement the earth of Segment Routing. It adds a new Segment Routing database
|
||||
to manage Segment Identifiers per Link and Prefix and Segment Routing enable node, Callback
|
||||
functions to process incoming LSA and install MPLS FIB entry through Zebra.
|
||||
|
||||
the figure below shows the relation between the various files:
|
||||
|
||||
- ospf_sr.c centralized all the Segment Routing processing. It receives Opaque LSA
|
||||
Router Information (4.0.0.0) from ospf_ri.c and Extended Prefix (7.0.0.X) Link (8.0.0.X)
|
||||
from ospf_ext.c. Once received, it parse TLVs and SubTLVs and store information in SRDB
|
||||
(which is defined in ospf_sr.h). For each received LSA, NHLFE is computed and send to
|
||||
Zebra to add/remove new MPLS labels entries and FEC. New CLI configurations are also
|
||||
centralized in ospf_sr.c. This CLI will trigger the flooding os new LSA Router Information
|
||||
(4.0.0.0), Extended Prefix (7.0.0.X) and Link (8.0.0.X) by ospf_ri.c, respectively ospf_ext.c.
|
||||
- ospf_ri.c send back to ospf_sr.c received Router Information LSA and update self Router
|
||||
Information LSA with paramters provided by ospf_sr.c i.e. SRGB and MSD. It use ospf_opaque.c
|
||||
functions to send / received these Opaque LSAs.
|
||||
- ospf_ext.c send bacl to ospf_sr.c received Extended Prefix and Link Opaque LSA and send
|
||||
self Extended Prefix and Link Opaque LSA through ospf_opaque.c functions.
|
||||
|
||||
+-----------+ +-------+
|
||||
| | | |
|
||||
| ospf_sr.c +-----+ SRDB |
|
||||
+-----------+ +--+ | |
|
||||
| +-^-------^-+ | +-------+
|
||||
| | | | |
|
||||
| | | | |
|
||||
| | | | +--------+
|
||||
| | | | |
|
||||
+---v----------+ | | | +-----v-------+
|
||||
| | | | | | |
|
||||
| ospf_ri.c +--+ | +-------+ ospf_ext.c |
|
||||
| LSA 4.0.0.0 | | | LSA 7.0.0.X |
|
||||
| | | | LSA 8.0.0.X |
|
||||
+---^----------+ | | |
|
||||
| | +-----^-------+
|
||||
| | |
|
||||
| | |
|
||||
| +--------v------------+ |
|
||||
| | | |
|
||||
| | ZEBRA: Labels + FEC | |
|
||||
| | | |
|
||||
| +---------------------+ |
|
||||
| |
|
||||
| |
|
||||
| +---------------+ |
|
||||
| | | |
|
||||
+---------> ospf_opaque.c <---------+
|
||||
| |
|
||||
+---------------+
|
||||
|
||||
|
||||
Known limitations
|
||||
-----------------
|
||||
|
||||
- Only single Area is supported. ABR is not yet supported
|
||||
- Only SPF algorithm is supported
|
||||
- Extended Prefix Range is not supported
|
||||
|
@ -22,6 +22,7 @@ networks.
|
||||
* Opaque LSA::
|
||||
* OSPF Traffic Engineering::
|
||||
* Router Information::
|
||||
* Segment Routing::
|
||||
* Debugging OSPF::
|
||||
* OSPF Configuration Examples::
|
||||
@end menu
|
||||
@ -724,6 +725,44 @@ Show Router Capabilities flag.
|
||||
Show Router Capabilities PCE parameters.
|
||||
@end deffn
|
||||
|
||||
@node Segment Routing
|
||||
@section Segment Routing
|
||||
|
||||
This is an EXPERIMENTAL support of Segment Routing as per draft
|
||||
draft-ietf-ospf-segment-routing-extensions-24i for MPLS dataplane.
|
||||
|
||||
@deffn {OSPF Command} {segment-routing on} {}
|
||||
@deffnx {OSPF Command} {no segment-routing} {}
|
||||
Enable Segment Routing. Even if this also activate routing information support,
|
||||
it is preferable to also activate routing information, and set accordingly the
|
||||
Area or AS flooding.
|
||||
@end deffn
|
||||
|
||||
@deffn {OSPF Command} {segment-routing global-block (0-1048575) (0-1048575)} {}
|
||||
@deffnx {OSPF Command} {no segment-routing global-block} {}
|
||||
Fix the Segment Routing Global Block i.e. the label range used by MPLS to store
|
||||
label in the MPLS FIB.
|
||||
@end deffn
|
||||
|
||||
@deffn {OSPF Command} {segment-routing node-msd (1-16)} {}
|
||||
@deffnx {OSPF Command} {no segment-routing node-msd} {}
|
||||
Fix the Maximum Stack Depth supported by the router. The value depend of the
|
||||
MPLS dataplane. E.g. for Linux kernel, since version 4.13 it is 32.
|
||||
@end deffn
|
||||
|
||||
@deffn {OSPF Command} {segment-routing prefix A.B.C.D/M index (0-65535)} {}
|
||||
@deffnx {OSPF Command} {no segment-routing prefix A.B.C.D/M} {}
|
||||
Set the Segment Rounting index for the specifyed prefix. Note
|
||||
that, only prefix with /32 corresponding to a loopback interface are
|
||||
currently supported.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {show ip ospf database segment-routing} {}
|
||||
@deffnx {Command} {show ip ospf database segment-routing adv-router @var{adv-router}} {}
|
||||
@deffnx {Command} {show ip ospf database segment-routing self-originate} {}
|
||||
Show Segment Routing Data Base, all SR nodes, specific advertized router or self router.
|
||||
@end deffn
|
||||
|
||||
@node Debugging OSPF
|
||||
@section Debugging OSPF
|
||||
|
||||
|
@ -358,6 +358,7 @@ struct cmd_node {
|
||||
#define OSPF_RI_STR "OSPF Router Information specific commands\n"
|
||||
#define PCE_STR "PCE Router Information specific commands\n"
|
||||
#define MPLS_STR "MPLS information\n"
|
||||
#define SR_STR "Segment-Routing specific commands\n"
|
||||
#define WATCHFRR_STR "watchfrr information\n"
|
||||
#define ZEBRA_STR "Zebra information\n"
|
||||
|
||||
|
@ -41,8 +41,10 @@
|
||||
#define MPLS_MAX_UNRESERVED_LABEL 1048575
|
||||
|
||||
/* Default min and max SRGB label range */
|
||||
#define MPLS_DEFAULT_MIN_SRGB_LABEL 16000
|
||||
#define MPLS_DEFAULT_MAX_SRGB_LABEL 23999
|
||||
#define MPLS_DEFAULT_MIN_SRGB_LABEL 10000
|
||||
#define MPLS_DEFAULT_MAX_SRGB_LABEL 50000
|
||||
#define MPLS_DEFAULT_MIN_SRGB_SIZE 5000
|
||||
#define MPLS_DEFAULT_MAX_SRGB_SIZE 20000
|
||||
|
||||
/* Maximum # labels that can be pushed. */
|
||||
#define MPLS_MAX_LABELS 16
|
||||
@ -94,7 +96,8 @@ enum lsp_types_t {
|
||||
ZEBRA_LSP_NONE = 0, /* No LSP. */
|
||||
ZEBRA_LSP_STATIC = 1, /* Static LSP. */
|
||||
ZEBRA_LSP_LDP = 2, /* LDP LSP. */
|
||||
ZEBRA_LSP_BGP = 3 /* BGP LSP. */
|
||||
ZEBRA_LSP_BGP = 3, /* BGP LSP. */
|
||||
ZEBRA_LSP_SR = 4 /* Segment Routing LSP. */
|
||||
};
|
||||
|
||||
/* Functions for basic label operations. */
|
||||
|
@ -78,6 +78,7 @@ ZEBRA_ROUTE_BGP_DIRECT, bgp-direct, NULL, 'b', 0, 0, "BGP-Direct"
|
||||
ZEBRA_ROUTE_BGP_DIRECT_EXT, bgp-direct-to-nve-groups, NULL, 'e', 0, 0, "BGP2VNC"
|
||||
ZEBRA_ROUTE_BABEL, babel, babeld, 'A', 1, 1, "Babel"
|
||||
ZEBRA_ROUTE_SHARP, sharp, sharpd, 'D', 1, 1, "SHARP"
|
||||
ZEBRA_ROUTE_OSPF_SR, ospf-sr, ospfd, 's', 1, 0, "OSPF-SR"
|
||||
ZEBRA_ROUTE_ALL, wildcard, none, '-', 0, 0, "-"
|
||||
|
||||
|
||||
@ -103,3 +104,4 @@ ZEBRA_ROUTE_LDP, "Label Distribution Protocol (LDP)"
|
||||
ZEBRA_ROUTE_VNC_DIRECT, "VNC direct (not via zebra) routes"
|
||||
ZEBRA_ROUTE_BABEL, "Babel routing protocol (Babel)"
|
||||
ZEBRA_ROUTE_SHARP, "Super Happy Advanced Routing Protocol (sharpd)"
|
||||
ZEBRA_ROUTE_OSPF_SR, "OSPF Segment Routing (OSPF-SR)"
|
||||
|
@ -51,6 +51,8 @@ unsigned long conf_debug_ospf_lsa = 0;
|
||||
unsigned long conf_debug_ospf_zebra = 0;
|
||||
unsigned long conf_debug_ospf_nssa = 0;
|
||||
unsigned long conf_debug_ospf_te = 0;
|
||||
unsigned long conf_debug_ospf_ext = 0;
|
||||
unsigned long conf_debug_ospf_sr = 0;
|
||||
|
||||
/* Enable debug option variables -- valid only session. */
|
||||
unsigned long term_debug_ospf_packet[5] = {0, 0, 0, 0, 0};
|
||||
@ -61,7 +63,8 @@ unsigned long term_debug_ospf_lsa = 0;
|
||||
unsigned long term_debug_ospf_zebra = 0;
|
||||
unsigned long term_debug_ospf_nssa = 0;
|
||||
unsigned long term_debug_ospf_te = 0;
|
||||
|
||||
unsigned long term_debug_ospf_ext = 0;
|
||||
unsigned long term_debug_ospf_sr = 0;
|
||||
|
||||
const char *ospf_redist_string(u_int route_type)
|
||||
{
|
||||
@ -1441,6 +1444,33 @@ DEFUN (no_debug_ospf_te,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (debug_ospf_sr,
|
||||
debug_ospf_sr_cmd,
|
||||
"debug ospf sr",
|
||||
DEBUG_STR
|
||||
OSPF_STR
|
||||
"OSPF-SR information\n")
|
||||
{
|
||||
if (vty->node == CONFIG_NODE)
|
||||
CONF_DEBUG_ON(sr, SR);
|
||||
TERM_DEBUG_ON(sr, SR);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_debug_ospf_sr,
|
||||
no_debug_ospf_sr_cmd,
|
||||
"no debug ospf sr",
|
||||
NO_STR
|
||||
DEBUG_STR
|
||||
OSPF_STR
|
||||
"OSPF-SR information\n")
|
||||
{
|
||||
if (vty->node == CONFIG_NODE)
|
||||
CONF_DEBUG_OFF(sr, SR);
|
||||
TERM_DEBUG_OFF(sr, SR);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_debug_ospf,
|
||||
no_debug_ospf_cmd,
|
||||
"no debug ospf",
|
||||
@ -1774,6 +1804,7 @@ void debug_init()
|
||||
install_element(ENABLE_NODE, &debug_ospf_event_cmd);
|
||||
install_element(ENABLE_NODE, &debug_ospf_nssa_cmd);
|
||||
install_element(ENABLE_NODE, &debug_ospf_te_cmd);
|
||||
install_element(ENABLE_NODE, &debug_ospf_sr_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_ism_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_nsm_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_lsa_cmd);
|
||||
@ -1781,6 +1812,7 @@ void debug_init()
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_event_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_nssa_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_te_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_ospf_sr_cmd);
|
||||
|
||||
install_element(ENABLE_NODE, &show_debugging_ospf_instance_cmd);
|
||||
install_element(ENABLE_NODE, &debug_ospf_packet_cmd);
|
||||
@ -1809,12 +1841,14 @@ void debug_init()
|
||||
install_element(CONFIG_NODE, &debug_ospf_event_cmd);
|
||||
install_element(CONFIG_NODE, &debug_ospf_nssa_cmd);
|
||||
install_element(CONFIG_NODE, &debug_ospf_te_cmd);
|
||||
install_element(CONFIG_NODE, &debug_ospf_sr_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_nsm_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_lsa_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_zebra_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_event_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_nssa_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_te_cmd);
|
||||
install_element(CONFIG_NODE, &no_debug_ospf_sr_cmd);
|
||||
|
||||
install_element(CONFIG_NODE, &debug_ospf_instance_nsm_cmd);
|
||||
install_element(CONFIG_NODE, &debug_ospf_instance_lsa_cmd);
|
||||
|
@ -57,6 +57,8 @@
|
||||
#define OSPF_DEBUG_EVENT 0x01
|
||||
#define OSPF_DEBUG_NSSA 0x02
|
||||
#define OSPF_DEBUG_TE 0x04
|
||||
#define OSPF_DEBUG_EXT 0x08
|
||||
#define OSPF_DEBUG_SR 0x10
|
||||
|
||||
/* Macro for setting debug option. */
|
||||
#define CONF_DEBUG_PACKET_ON(a, b) conf_debug_ospf_packet[a] |= (b)
|
||||
@ -98,6 +100,10 @@
|
||||
|
||||
#define IS_DEBUG_OSPF_TE IS_DEBUG_OSPF(te,TE)
|
||||
|
||||
#define IS_DEBUG_OSPF_EXT IS_DEBUG_OSPF(ext,EXT)
|
||||
|
||||
#define IS_DEBUG_OSPF_SR IS_DEBUG_OSPF(sr,SR)
|
||||
|
||||
#define IS_CONF_DEBUG_OSPF_PACKET(a, b) \
|
||||
(conf_debug_ospf_packet[a] & OSPF_DEBUG_##b)
|
||||
#define IS_CONF_DEBUG_OSPF(a, b) (conf_debug_ospf_##a & OSPF_DEBUG_##b)
|
||||
@ -119,6 +125,8 @@ extern unsigned long term_debug_ospf_lsa;
|
||||
extern unsigned long term_debug_ospf_zebra;
|
||||
extern unsigned long term_debug_ospf_nssa;
|
||||
extern unsigned long term_debug_ospf_te;
|
||||
extern unsigned long term_debug_ospf_ext;
|
||||
extern unsigned long term_debug_ospf_sr;
|
||||
|
||||
/* Message Strings. */
|
||||
extern char *ospf_lsa_type_str[];
|
||||
|
1769
ospfd/ospf_ext.c
Normal file
1769
ospfd/ospf_ext.c
Normal file
File diff suppressed because it is too large
Load Diff
196
ospfd/ospf_ext.h
Normal file
196
ospfd/ospf_ext.h
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* This is an implementation of RFC7684 OSPFv2 Prefix/Link Attribute
|
||||
* Advertisement
|
||||
*
|
||||
* Module name: Extended Prefix/Link Opaque LSA header definition
|
||||
*
|
||||
* Author: Anselme Sawadogo <anselmesawadogo@gmail.com>
|
||||
* Author: Olivier Dugeon <olivier.dugeon@orange.com>
|
||||
*
|
||||
* Copyright (C) 2016 - 2017 Orange Labs http://www.orange.com
|
||||
*
|
||||
* This file is part of FRR.
|
||||
*
|
||||
* FRR is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* FRR is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with FRR; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _FRR_OSPF_EXT_PREF_H_
|
||||
#define _FRR_OSPF_EXT_PREF_H_
|
||||
|
||||
/*
|
||||
* Opaque LSA's link state ID for Extended Prefix/Link is
|
||||
* structured as follows.
|
||||
*
|
||||
* 24 16 8 0
|
||||
* +--------+--------+--------+--------+
|
||||
* | 7/8 |........|........|........|
|
||||
* +--------+--------+--------+--------+
|
||||
* |<-Type->|<------- Instance ------->|
|
||||
*
|
||||
*
|
||||
* Type: IANA has assigned '7' for Extended Prefix Opaque LSA
|
||||
* and '8' for Extended Link Opaque LSA
|
||||
* Instance: User may select arbitrary 24-bit values to identify
|
||||
* different instances of Extended Prefix/Link Opaque LSA
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 24 16 8 0
|
||||
* +--------+--------+--------+--------+ ---
|
||||
* | LS age |Options | 10,11 | A
|
||||
* +--------+--------+--------+--------+ | Standard (Opaque) LSA header;
|
||||
* | 7/8 | Instance | |
|
||||
* +--------+--------+--------+--------+ | Type 10 or 11 are used for Extended
|
||||
* | Advertising router | | Prefix Opaque LSA
|
||||
* +--------+--------+--------+--------+ |
|
||||
* | LS sequence number | | Type 10 only is used for Extended
|
||||
* +--------+--------+--------+--------+ | Link Opaque LSA
|
||||
* | LS checksum | Length | V
|
||||
* +--------+--------+--------+--------+ ---
|
||||
* | Type | Length | A
|
||||
* +--------+--------+--------+--------+ | TLV part for Extended Prefix/Link
|
||||
* | | | Opaque LSA;
|
||||
* ~ Values ... ~ | Values might be structured as a set
|
||||
* | | V of sub-TLVs.
|
||||
* +--------+--------+--------+--------+ ---
|
||||
*/
|
||||
|
||||
/* Global use constant numbers */
|
||||
|
||||
#define MAX_LEGAL_EXT_INSTANCE_NUM (0xffff)
|
||||
#define LEGAL_EXT_INSTANCE_RANGE(i) (0 <= (i) && (i) <= 0xffff)
|
||||
|
||||
/* Flags to manage Extended Link/Prefix Opaque LSA */
|
||||
#define EXT_LPFLG_LSA_INACTIVE 0x00
|
||||
#define EXT_LPFLG_LSA_ACTIVE 0x01
|
||||
#define EXT_LPFLG_LSA_ENGAGED 0x02
|
||||
#define EXT_LPFLG_LSA_LOOKUP_DONE 0x04
|
||||
#define EXT_LPFLG_LSA_FORCED_REFRESH 0x08
|
||||
#define EXT_LPFLG_FIB_ENTRY_SET 0x10
|
||||
|
||||
/*
|
||||
* Following section defines TLV (tag, length, value) structures,
|
||||
* used in Extended Prefix/Link Opaque LSA.
|
||||
*/
|
||||
|
||||
/* Extended Prefix TLV Route Types */
|
||||
#define EXT_TLV_PREF_ROUTE_UNSPEC 0
|
||||
#define EXT_TLV_PREF_ROUTE_INTRA_AREA 1
|
||||
#define EXT_TLV_PREF_ROUTE_INTER_AREA 3
|
||||
#define EXT_TLV_PREF_ROUTE_AS_EXT 5
|
||||
#define EXT_TLV_PREF_ROUTE_NSSA_EXT 7
|
||||
|
||||
/* Extended Prefix and Extended Prefix Range TLVs'
|
||||
* Address family flag for IPv4 */
|
||||
#define EXT_TLV_PREF_AF_IPV4 0
|
||||
|
||||
/* Extended Prefix TLV Flags */
|
||||
#define EXT_TLV_PREF_AFLG 0x80
|
||||
#define EXT_TLV_PREF_NFLG 0x40
|
||||
|
||||
/* Extended Prefix Range TLV Flags */
|
||||
#define EXT_TLV_PREF_RANGE_IAFLG 0x80
|
||||
|
||||
/* ERO subtlvs Flags */
|
||||
#define EXT_SUBTLV_ERO_LFLG 0x80
|
||||
|
||||
/* Extended Prefix TLV see RFC 7684 section 2.1 */
|
||||
#define EXT_TLV_PREFIX 1
|
||||
#define EXT_TLV_PREFIX_SIZE 8
|
||||
struct ext_tlv_prefix {
|
||||
struct tlv_header header;
|
||||
u_int8_t route_type;
|
||||
u_int8_t pref_length;
|
||||
u_int8_t af;
|
||||
u_int8_t flags;
|
||||
struct in_addr address;
|
||||
};
|
||||
|
||||
/* Extended Link TLV see RFC 7684 section 3.1 */
|
||||
#define EXT_TLV_LINK 1
|
||||
#define EXT_TLV_LINK_SIZE 12
|
||||
struct ext_tlv_link {
|
||||
struct tlv_header header;
|
||||
u_int8_t link_type;
|
||||
u_int8_t reserved[3];
|
||||
struct in_addr link_id;
|
||||
struct in_addr link_data;
|
||||
};
|
||||
|
||||
/* Remote Interface Address Sub-TLV, Cisco experimental use Sub-TLV */
|
||||
#define EXT_SUBTLV_RMT_ITF_ADDR 32768
|
||||
#define EXT_SUBTLV_RMT_ITF_ADDR_SIZE 4
|
||||
struct ext_subtlv_rmt_itf_addr {
|
||||
struct tlv_header header;
|
||||
struct in_addr value;
|
||||
};
|
||||
|
||||
/* Internal structure to manage Extended Link/Prefix Opaque LSA */
|
||||
struct ospf_ext_lp {
|
||||
bool enabled;
|
||||
|
||||
/* Flags to manage this Extended Prefix/Link Opaque LSA */
|
||||
u_int32_t flags;
|
||||
|
||||
/* Scope is area Opaque Type 10 or AS Opaque LSA Type 11 for
|
||||
* Extended Prefix and area Opaque Type 10 for Extended Link */
|
||||
u_int8_t scope;
|
||||
|
||||
/* area pointer if flooding is Type 10 Null if flooding is AS scope */
|
||||
struct ospf_area *area;
|
||||
struct in_addr area_id;
|
||||
|
||||
/* List of interface with Segment Routing enable */
|
||||
struct list *iflist;
|
||||
};
|
||||
|
||||
/* Structure to aggregate interfaces information for Extended Prefix/Link */
|
||||
struct ext_itf {
|
||||
/* 24-bit Opaque-ID field value according to RFC 7684 specification */
|
||||
u_int32_t instance;
|
||||
u_int8_t type; /* Extended Prefix (7) or Link (8) */
|
||||
|
||||
/* Reference pointer to a Zebra-interface. */
|
||||
struct interface *ifp;
|
||||
|
||||
/* Area info in which this SR link belongs to. */
|
||||
struct ospf_area *area;
|
||||
|
||||
/* Flags to manage this link parameters. */
|
||||
u_int32_t flags;
|
||||
|
||||
/* SID type: Node, Adjacency or LAN Adjacency */
|
||||
enum sid_type stype;
|
||||
|
||||
/* extended link/prefix TLV information */
|
||||
struct ext_tlv_prefix prefix;
|
||||
struct ext_subtlv_prefix_sid node_sid;
|
||||
struct ext_tlv_link link;
|
||||
struct ext_subtlv_adj_sid adj_sid[2];
|
||||
struct ext_subtlv_lan_adj_sid lan_sid[2];
|
||||
|
||||
/* cisco experimental subtlv */
|
||||
struct ext_subtlv_rmt_itf_addr rmt_itf_addr;
|
||||
};
|
||||
|
||||
/* Prototypes. */
|
||||
extern int ospf_ext_init(void);
|
||||
extern void ospf_ext_term(void);
|
||||
extern void ospf_ext_update_sr(bool);
|
||||
extern int ospf_ext_schedule_prefix_index(struct interface *, u_int32_t,
|
||||
struct prefix_ipv4 *);
|
||||
#endif /* _FRR_OSPF_EXT_PREF_H_ */
|
@ -53,3 +53,5 @@ DEFINE_MTYPE(OSPFD, OSPF_IF_PARAMS, "OSPF if params")
|
||||
DEFINE_MTYPE(OSPFD, OSPF_MESSAGE, "OSPF message")
|
||||
DEFINE_MTYPE(OSPFD, OSPF_MPLS_TE, "OSPF MPLS parameters")
|
||||
DEFINE_MTYPE(OSPFD, OSPF_PCE_PARAMS, "OSPF PCE parameters")
|
||||
DEFINE_MTYPE(OSPFD, OSPF_EXT_PARAMS, "OSPF Extended parameters")
|
||||
DEFINE_MTYPE(OSPFD, OSPF_SR_PARAMS, "OSPF Segment Routing parameters")
|
||||
|
@ -52,5 +52,7 @@ DECLARE_MTYPE(OSPF_IF_PARAMS)
|
||||
DECLARE_MTYPE(OSPF_MESSAGE)
|
||||
DECLARE_MTYPE(OSPF_MPLS_TE)
|
||||
DECLARE_MTYPE(OSPF_PCE_PARAMS)
|
||||
DECLARE_MTYPE(OSPF_SR_PARAMS)
|
||||
DECLARE_MTYPE(OSPF_EXT_PARAMS)
|
||||
|
||||
#endif /* _QUAGGA_OSPF_MEMORY_H */
|
||||
|
@ -50,6 +50,10 @@
|
||||
#include "ospfd/ospf_route.h"
|
||||
#include "ospfd/ospf_ase.h"
|
||||
#include "ospfd/ospf_zebra.h"
|
||||
#include "ospfd/ospf_te.h"
|
||||
#include "ospfd/ospf_sr.h"
|
||||
#include "ospfd/ospf_ri.h"
|
||||
#include "ospfd/ospf_ext.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(OSPFD, OSPF_OPAQUE_FUNCTAB, "OSPF opaque function table")
|
||||
DEFINE_MTYPE_STATIC(OSPFD, OPAQUE_INFO_PER_TYPE, "OSPF opaque per-type info")
|
||||
@ -59,9 +63,6 @@ DEFINE_MTYPE_STATIC(OSPFD, OPAQUE_INFO_PER_ID, "OSPF opaque per-ID info")
|
||||
* Followings are initialize/terminate functions for Opaque-LSAs handling.
|
||||
*------------------------------------------------------------------------*/
|
||||
|
||||
#include "ospfd/ospf_te.h"
|
||||
#include "ospfd/ospf_ri.h"
|
||||
|
||||
#ifdef SUPPORT_OSPF_API
|
||||
int ospf_apiserver_init(void);
|
||||
void ospf_apiserver_term(void);
|
||||
@ -85,9 +86,17 @@ void ospf_opaque_init(void)
|
||||
if (ospf_mpls_te_init() != 0)
|
||||
exit(1);
|
||||
|
||||
/* Segment Routing init */
|
||||
if (ospf_sr_init() != 0)
|
||||
exit(1);
|
||||
|
||||
if (ospf_router_info_init() != 0)
|
||||
exit(1);
|
||||
|
||||
/* Force Extended Prefix/Link to Type 10 */
|
||||
if (ospf_ext_init() != 0)
|
||||
exit(1);
|
||||
|
||||
#ifdef SUPPORT_OSPF_API
|
||||
if ((ospf_apiserver_enable) && (ospf_apiserver_init() != 0))
|
||||
exit(1);
|
||||
@ -102,6 +111,10 @@ void ospf_opaque_term(void)
|
||||
|
||||
ospf_router_info_term();
|
||||
|
||||
ospf_ext_term();
|
||||
|
||||
ospf_sr_term();
|
||||
|
||||
#ifdef SUPPORT_OSPF_API
|
||||
ospf_apiserver_term();
|
||||
#endif /* SUPPORT_OSPF_API */
|
||||
@ -209,6 +222,12 @@ static const char *ospf_opaque_type_name(u_char opaque_type)
|
||||
case OPAQUE_TYPE_ROUTER_INFORMATION_LSA:
|
||||
name = "Router Information LSA";
|
||||
break;
|
||||
case OPAQUE_TYPE_EXTENDED_PREFIX_LSA:
|
||||
name = "Extended Prefix Opaque LSA";
|
||||
break;
|
||||
case OPAQUE_TYPE_EXTENDED_LINK_LSA:
|
||||
name = "Extended Link Opaque LSA";
|
||||
break;
|
||||
default:
|
||||
if (OPAQUE_TYPE_RANGE_UNASSIGNED(opaque_type))
|
||||
name = "Unassigned";
|
||||
|
@ -59,7 +59,9 @@
|
||||
#define OPAQUE_TYPE_L1VPN_LSA 5
|
||||
#define OPAQUE_TYPE_ROUTER_INFORMATION_LSA 4
|
||||
#define OPAQUE_TYPE_INTER_AS_LSA 6
|
||||
#define OPAQUE_TYPE_MAX 6
|
||||
#define OPAQUE_TYPE_EXTENDED_PREFIX_LSA 7
|
||||
#define OPAQUE_TYPE_EXTENDED_LINK_LSA 8
|
||||
#define OPAQUE_TYPE_MAX 8
|
||||
|
||||
/* Followings types are proposed in internet-draft documents. */
|
||||
#define OPAQUE_TYPE_8021_QOSPF 129
|
||||
|
423
ospfd/ospf_ri.c
423
ospfd/ospf_ri.c
@ -3,9 +3,8 @@
|
||||
* with support of RFC5088 PCE Capabilites announcement
|
||||
*
|
||||
* Module name: Router Information
|
||||
* Version: 0.99.22
|
||||
* Created: 2012-02-01 by Olivier Dugeon
|
||||
* Copyright (C) 2012 Orange Labs http://www.orange.com/
|
||||
* Author: Olivier Dugeon <olivier.dugeon@orange.com>
|
||||
* Copyright (C) 2012 - 2017 Orange Labs http://www.orange.com/
|
||||
*
|
||||
* This file is part of GNU Quagga.
|
||||
*
|
||||
@ -39,6 +38,7 @@
|
||||
#include "thread.h"
|
||||
#include "hash.h"
|
||||
#include "sockunion.h" /* for inet_aton() */
|
||||
#include "mpls.h"
|
||||
|
||||
#include "ospfd/ospfd.h"
|
||||
#include "ospfd/ospf_interface.h"
|
||||
@ -55,8 +55,8 @@
|
||||
#include "ospfd/ospf_route.h"
|
||||
#include "ospfd/ospf_ase.h"
|
||||
#include "ospfd/ospf_zebra.h"
|
||||
#include "ospfd/ospf_sr.h"
|
||||
#include "ospfd/ospf_ri.h"
|
||||
#include "ospfd/ospf_te.h"
|
||||
|
||||
/* Store Router Information PCE TLV and SubTLV in network byte order. */
|
||||
struct ospf_pce_info {
|
||||
@ -69,6 +69,20 @@ struct ospf_pce_info {
|
||||
struct ri_pce_subtlv_cap_flag pce_cap_flag;
|
||||
};
|
||||
|
||||
/* Store Router Information Segment Routing TLV and SubTLV in network byte order. */
|
||||
struct ospf_ri_sr_info {
|
||||
bool enabled;
|
||||
/* Algorithms supported by the node */
|
||||
struct ri_sr_tlv_sr_algorithm algo;
|
||||
/*
|
||||
* Segment Routing Global Block i.e. label range
|
||||
* Only one range supported in this code
|
||||
*/
|
||||
struct ri_sr_tlv_sid_label_range range;
|
||||
/* Maximum SID Depth supported by the node */
|
||||
struct ri_sr_tlv_node_msd msd;
|
||||
};
|
||||
|
||||
/* Following structure are internal use only. */
|
||||
struct ospf_router_info {
|
||||
bool enabled;
|
||||
@ -77,7 +91,7 @@ struct ospf_router_info {
|
||||
u_int8_t scope;
|
||||
|
||||
/* Flags to manage this router information. */
|
||||
#define RIFLG_LSA_ENGAGED 0x1
|
||||
#define RIFLG_LSA_ENGAGED 0x1
|
||||
#define RIFLG_LSA_FORCED_REFRESH 0x2
|
||||
u_int32_t flags;
|
||||
|
||||
@ -90,6 +104,9 @@ struct ospf_router_info {
|
||||
|
||||
/* Store PCE capability LSA */
|
||||
struct ospf_pce_info pce_info;
|
||||
|
||||
/* Store SR capability LSA */
|
||||
struct ospf_ri_sr_info sr_info;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -113,15 +130,19 @@ static int ospf_router_info_lsa_originate(void *arg);
|
||||
static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa);
|
||||
static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode);
|
||||
static void ospf_router_info_register_vty(void);
|
||||
static int ospf_router_info_lsa_update(struct ospf_lsa *lsa);
|
||||
static void del_pce_info(void *val);
|
||||
|
||||
int ospf_router_info_init(void)
|
||||
{
|
||||
|
||||
zlog_info("RI -> Initialize Router Information");
|
||||
|
||||
memset(&OspfRI, 0, sizeof(struct ospf_router_info));
|
||||
OspfRI.enabled = false;
|
||||
OspfRI.registered = 0;
|
||||
OspfRI.scope = OSPF_OPAQUE_AS_LSA;
|
||||
OspfRI.area_id.s_addr = 0;
|
||||
OspfRI.flags = 0;
|
||||
|
||||
/* Initialize pce domain and neighbor list */
|
||||
@ -131,6 +152,9 @@ int ospf_router_info_init(void)
|
||||
OspfRI.pce_info.pce_neighbor = list_new();
|
||||
OspfRI.pce_info.pce_neighbor->del = del_pce_info;
|
||||
|
||||
/* Initialize Segment Routing information structure */
|
||||
OspfRI.sr_info.enabled = false;
|
||||
|
||||
ospf_router_info_register_vty();
|
||||
|
||||
return 0;
|
||||
@ -143,19 +167,22 @@ static int ospf_router_info_register(u_int8_t scope)
|
||||
if (OspfRI.registered)
|
||||
return rc;
|
||||
|
||||
zlog_info("Register Router Information with scope %s(%d)",
|
||||
zlog_info("RI -> Register Router Information with scope %s(%d)",
|
||||
scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope);
|
||||
rc = ospf_register_opaque_functab(
|
||||
scope, OPAQUE_TYPE_ROUTER_INFORMATION_LSA,
|
||||
NULL, /* new interface */
|
||||
NULL, /* del interface */
|
||||
ospf_router_info_ism_change, ospf_router_info_nsm_change,
|
||||
ospf_router_info_ism_change,
|
||||
ospf_router_info_nsm_change,
|
||||
ospf_router_info_config_write_router,
|
||||
NULL, /* Config. write interface */
|
||||
NULL, /* Config. write debug */
|
||||
ospf_router_info_show_info, ospf_router_info_lsa_originate,
|
||||
ospf_router_info_lsa_refresh, NULL, /* new_lsa_hook */
|
||||
NULL); /* del_lsa_hook */
|
||||
ospf_router_info_show_info,
|
||||
ospf_router_info_lsa_originate,
|
||||
ospf_router_info_lsa_refresh,
|
||||
ospf_router_info_lsa_update,
|
||||
NULL); /* del_lsa_hook */
|
||||
|
||||
if (rc != 0) {
|
||||
zlog_warn(
|
||||
@ -204,6 +231,20 @@ static void del_pce_info(void *val)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Catch RI LSA flooding Scope for ospf_ext.[h,c] code */
|
||||
struct scope_info ospf_router_info_get_flooding_scope(void)
|
||||
{
|
||||
struct scope_info flooding_scope;
|
||||
if (OspfRI.scope == OSPF_OPAQUE_AS_LSA) {
|
||||
flooding_scope.scope = OSPF_OPAQUE_AS_LSA;
|
||||
flooding_scope.area_id.s_addr = 0;
|
||||
return flooding_scope;
|
||||
}
|
||||
flooding_scope.scope = OSPF_OPAQUE_AREA_LSA;
|
||||
flooding_scope.area_id.s_addr = OspfRI.area_id.s_addr;
|
||||
return flooding_scope;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* Followings are control functions for ROUTER INFORMATION parameters
|
||||
*management.
|
||||
@ -399,6 +440,84 @@ static void set_pce_cap_flag(u_int32_t cap, struct ospf_pce_info *pce)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Segment Routing TLV setter */
|
||||
|
||||
/* Algorithm SubTLV - section 3.1 */
|
||||
static void set_sr_algorithm(u_int8_t algo)
|
||||
{
|
||||
|
||||
OspfRI.sr_info.algo.value[0] = algo;
|
||||
for (int i = 1; i < ALGORITHM_COUNT; i++)
|
||||
OspfRI.sr_info.algo.value[i] = SR_ALGORITHM_UNSET;
|
||||
|
||||
/* Set TLV type and length == only 1 Algorithm */
|
||||
TLV_TYPE(OspfRI.sr_info.algo) = htons(RI_SR_TLV_SR_ALGORITHM);
|
||||
TLV_LEN(OspfRI.sr_info.algo) = htons(sizeof(u_int8_t));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* unset Aglogithm SubTLV */
|
||||
static void unset_sr_algorithm(u_int8_t algo)
|
||||
{
|
||||
|
||||
for (int i = 0; i < ALGORITHM_COUNT; i++)
|
||||
OspfRI.sr_info.algo.value[i] = SR_ALGORITHM_UNSET;
|
||||
|
||||
/* Unset TLV type and length */
|
||||
TLV_TYPE(OspfRI.sr_info.algo) = htons(0);
|
||||
TLV_LEN(OspfRI.sr_info.algo) = htons(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Segment Routing Global Block SubTLV - section 3.2 */
|
||||
static void set_sr_sid_label_range(struct sr_srgb srgb)
|
||||
{
|
||||
/* Set Header */
|
||||
TLV_TYPE(OspfRI.sr_info.range) = htons(RI_SR_TLV_SID_LABEL_RANGE);
|
||||
TLV_LEN(OspfRI.sr_info.range) =
|
||||
htons(SUBTLV_SID_LABEL_SIZE + sizeof(u_int32_t));
|
||||
/* Set Range Size */
|
||||
OspfRI.sr_info.range.size = htonl(SET_RANGE_SIZE(srgb.range_size));
|
||||
/* Set Lower bound label SubTLV */
|
||||
TLV_TYPE(OspfRI.sr_info.range.lower) = htons(SUBTLV_SID_LABEL);
|
||||
TLV_LEN(OspfRI.sr_info.range.lower) = htons(SID_RANGE_LABEL_LENGTH);
|
||||
OspfRI.sr_info.range.lower.value = htonl(SET_LABEL(srgb.lower_bound));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unset this SRGB SubTLV */
|
||||
static void unset_sr_sid_label_range()
|
||||
{
|
||||
|
||||
TLV_TYPE(OspfRI.sr_info.range) = htons(0);
|
||||
TLV_LEN(OspfRI.sr_info.range) = htons(0);
|
||||
TLV_TYPE(OspfRI.sr_info.range.lower) = htons(0);
|
||||
TLV_LEN(OspfRI.sr_info.range.lower) = htons(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set Maximum Stack Depth for this router */
|
||||
static void set_sr_node_msd(u_int8_t msd)
|
||||
{
|
||||
TLV_TYPE(OspfRI.sr_info.msd) = htons(RI_SR_TLV_NODE_MSD);
|
||||
TLV_LEN(OspfRI.sr_info.msd) = htons(sizeof(u_int32_t));
|
||||
OspfRI.sr_info.msd.value = msd;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unset this router MSD */
|
||||
static void unset_sr_node_msd()
|
||||
{
|
||||
TLV_TYPE(OspfRI.sr_info.msd) = htons(0);
|
||||
TLV_LEN(OspfRI.sr_info.msd) = htons(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void unset_param(struct tlv_header *tlv)
|
||||
{
|
||||
@ -466,11 +585,62 @@ static int is_mandated_params_set(struct ospf_router_info ori)
|
||||
&& (ntohs(ori.pce_info.pce_cap_flag.header.type) == 0))
|
||||
return rc;
|
||||
|
||||
if ((ori.sr_info.enabled) && (ntohs(TLV_TYPE(ori.sr_info.algo)) == 0)
|
||||
&& (ntohs(TLV_TYPE(ori.sr_info.range)) == 0))
|
||||
return rc;
|
||||
|
||||
rc = 1;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Used by Segment Routing to set new TLVs and Sub-TLVs values
|
||||
*
|
||||
* @param enable To activate or not Segment Routing router Information flooding
|
||||
* @param size Size of Label Range i.e. SRGB size
|
||||
* @param lower Lower bound of the Label Range i.e. SRGB first label
|
||||
* @param msd Maximum label Stack Depth suported by the router
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, u_int8_t msd)
|
||||
{
|
||||
|
||||
/* First activate and initialize Router Information is necessary */
|
||||
if (!OspfRI.enabled) {
|
||||
OspfRI.enabled = true;
|
||||
initialize_params(&OspfRI);
|
||||
}
|
||||
|
||||
if (IS_DEBUG_OSPF_SR)
|
||||
zlog_debug("RI-> %s Routing Information for Segment Routing",
|
||||
enable ? "Enable" : "Disable");
|
||||
|
||||
/* Unset or Set SR parameters */
|
||||
if (!enable) {
|
||||
unset_sr_algorithm(SR_ALGORITHM_SPF);
|
||||
unset_sr_sid_label_range();
|
||||
unset_sr_node_msd();
|
||||
OspfRI.sr_info.enabled = false;
|
||||
} else {
|
||||
// Only SR_ALGORITHM_SPF is supported
|
||||
set_sr_algorithm(SR_ALGORITHM_SPF);
|
||||
set_sr_sid_label_range(srgb);
|
||||
if (msd != 0)
|
||||
set_sr_node_msd(msd);
|
||||
else
|
||||
unset_sr_node_msd();
|
||||
OspfRI.sr_info.enabled = true;
|
||||
}
|
||||
|
||||
/* Refresh if already engaged or originate RI LSA */
|
||||
if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED))
|
||||
ospf_router_info_lsa_schedule(REFRESH_THIS_LSA);
|
||||
else
|
||||
ospf_router_info_lsa_schedule(REORIGINATE_THIS_LSA);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* Followings are callback functions against generic Opaque-LSAs handling.
|
||||
*------------------------------------------------------------------------*/
|
||||
@ -519,12 +689,22 @@ static void ospf_router_info_lsa_body_set(struct stream *s)
|
||||
/* Build Router Information TLV */
|
||||
build_tlv(s, &OspfRI.router_cap.header);
|
||||
|
||||
/* Compute PCE Info header first */
|
||||
set_pce_header (&OspfRI.pce_info);
|
||||
/* Build Segment Routing TLVs if enabled */
|
||||
if (OspfRI.sr_info.enabled) {
|
||||
/* Build Algorithm TLV */
|
||||
build_tlv(s, &TLV_HDR(OspfRI.sr_info.algo));
|
||||
/* Build SRGB TLV */
|
||||
build_tlv(s, &TLV_HDR(OspfRI.sr_info.range));
|
||||
/* Build MSD TLV */
|
||||
build_tlv(s, &TLV_HDR(OspfRI.sr_info.msd));
|
||||
}
|
||||
|
||||
/* Add RI PCE TLV if it is set */
|
||||
if (OspfRI.pce_info.enabled) {
|
||||
|
||||
/* Compute PCE Info header first */
|
||||
set_pce_header (&OspfRI.pce_info);
|
||||
|
||||
/* Build PCE TLV */
|
||||
build_tlv_header(s, &OspfRI.pce_info.pce_header.header);
|
||||
|
||||
@ -855,6 +1035,38 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Callback to handle Segment Routing information */
|
||||
static int ospf_router_info_lsa_update(struct ospf_lsa *lsa)
|
||||
{
|
||||
|
||||
/* Sanity Check */
|
||||
if (lsa == NULL) {
|
||||
zlog_warn("OSPF-RI (ospf_router_info_lsa_update): Abort! LSA is NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if it is not my LSA */
|
||||
if (IS_LSA_SELF(lsa))
|
||||
return 0;
|
||||
|
||||
/* Process only Router Information LSA */
|
||||
if (GET_OPAQUE_TYPE(
|
||||
ntohl(lsa->data->id.s_addr)) != OPAQUE_TYPE_ROUTER_INFORMATION_LSA)
|
||||
return 0;
|
||||
|
||||
/* Check if Router Info & Segment Routing are enable */
|
||||
if (!OspfRI.enabled || !OspfRI.sr_info.enabled)
|
||||
return 0;
|
||||
|
||||
/* Call Segment Routing LSA update or deletion */
|
||||
if (!IS_LSA_MAXAGE(lsa))
|
||||
ospf_sr_ri_lsa_update(lsa);
|
||||
else
|
||||
ospf_sr_ri_lsa_delete(lsa);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* Followings are vty session control functions.
|
||||
*------------------------------------------------------------------------*/
|
||||
@ -1021,6 +1233,98 @@ static u_int16_t show_vty_pce_info(struct vty *vty, struct tlv_header *ri,
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* Display Segment Routing Algorithm TLV information */
|
||||
static u_int16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh)
|
||||
{
|
||||
struct ri_sr_tlv_sr_algorithm *algo =
|
||||
(struct ri_sr_tlv_sr_algorithm *)tlvh;
|
||||
int i;
|
||||
if (vty != NULL) {
|
||||
vty_out(vty, " Segment Routing Algorithm TLV:\n");
|
||||
for (i = 0; i < ntohs(algo->header.length); i++) {
|
||||
switch (algo->value[i]) {
|
||||
case 0:
|
||||
vty_out(vty, " Algorithm %d: SPF\n", i);
|
||||
break;
|
||||
case 1:
|
||||
vty_out(vty, " Algorithm %d: Strict SPF\n",
|
||||
i);
|
||||
break;
|
||||
default:
|
||||
vty_out(vty,
|
||||
" Algorithm %d: Unknown value %d\n", i,
|
||||
algo->value[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
zlog_debug(" Segment Routing Algorithm TLV:\n");
|
||||
for (i = 0; i < ntohs(algo->header.length); i++)
|
||||
switch (algo->value[i]) {
|
||||
case 0:
|
||||
zlog_debug(" Algorithm %d: SPF\n", i);
|
||||
break;
|
||||
case 1:
|
||||
zlog_debug(" Algorithm %d: Strict SPF\n", i);
|
||||
break;
|
||||
default:
|
||||
zlog_debug(
|
||||
" Algorithm %d: Unknown value %d\n",
|
||||
i, algo->value[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TLV_SIZE(tlvh);
|
||||
}
|
||||
|
||||
/* Display Segment Routing SID/Label Range TLV information */
|
||||
static u_int16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh)
|
||||
{
|
||||
struct ri_sr_tlv_sid_label_range *range =
|
||||
(struct ri_sr_tlv_sid_label_range *)tlvh;
|
||||
|
||||
if (vty != NULL) {
|
||||
vty_out(vty,
|
||||
" Segment Routing Range TLV:\n"
|
||||
" Range Size = %d\n"
|
||||
" SID Label = %d\n\n",
|
||||
GET_RANGE_SIZE(ntohl(range->size)),
|
||||
GET_LABEL(ntohl(range->lower.value)));
|
||||
} else {
|
||||
zlog_debug(
|
||||
" Segment Routing Range TLV:\n"
|
||||
" Range Size = %d\n"
|
||||
" SID Label = %d\n\n",
|
||||
GET_RANGE_SIZE(ntohl(range->size)),
|
||||
GET_LABEL(ntohl(range->lower.value)));
|
||||
}
|
||||
|
||||
return TLV_SIZE(tlvh);
|
||||
}
|
||||
|
||||
/* Display Segment Routing Maximum Stack Depth TLV information */
|
||||
static u_int16_t show_vty_sr_msd(struct vty *vty, struct tlv_header *tlvh)
|
||||
{
|
||||
struct ri_sr_tlv_node_msd *msd = (struct ri_sr_tlv_node_msd *)tlvh;
|
||||
|
||||
if (vty != NULL) {
|
||||
vty_out(vty,
|
||||
" Segment Routing MSD TLV:\n"
|
||||
" Node Maximum Stack Depth = %d\n",
|
||||
msd->value);
|
||||
} else {
|
||||
zlog_debug(
|
||||
" Segment Routing MSD TLV:\n"
|
||||
" Node Maximum Stack Depth = %d\n",
|
||||
msd->value);
|
||||
}
|
||||
|
||||
return TLV_SIZE(tlvh);
|
||||
}
|
||||
|
||||
static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
||||
{
|
||||
struct lsa_header *lsah = (struct lsa_header *)lsa->data;
|
||||
@ -1041,6 +1345,16 @@ static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
||||
sum += TLV_HDR_SIZE;
|
||||
sum += show_vty_pce_info(vty, tlvh, length - sum);
|
||||
break;
|
||||
case RI_SR_TLV_SR_ALGORITHM:
|
||||
sum += show_vty_sr_algorithm(vty, tlvh);
|
||||
break;
|
||||
case RI_SR_TLV_SID_LABEL_RANGE:
|
||||
sum += show_vty_sr_range(vty, tlvh);
|
||||
break;
|
||||
case RI_SR_TLV_NODE_MSD:
|
||||
sum += show_vty_sr_msd(vty, tlvh);
|
||||
break;
|
||||
|
||||
default:
|
||||
sum += show_vty_unknown_tlv(vty, tlvh);
|
||||
break;
|
||||
@ -1058,53 +1372,54 @@ static void ospf_router_info_config_write_router(struct vty *vty)
|
||||
struct ri_pce_subtlv_neighbor *neighbor;
|
||||
struct in_addr tmp;
|
||||
|
||||
if (OspfRI.enabled) {
|
||||
if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
|
||||
vty_out(vty, " router-info as\n");
|
||||
else
|
||||
vty_out(vty, " router-info area %s\n",
|
||||
inet_ntoa(OspfRI.area_id));
|
||||
if (!OspfRI.enabled)
|
||||
return;
|
||||
|
||||
if (OspfRI.pce_info.enabled) {
|
||||
if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
|
||||
vty_out(vty, " router-info as\n");
|
||||
else
|
||||
vty_out(vty, " router-info area %s\n",
|
||||
inet_ntoa(OspfRI.area_id));
|
||||
|
||||
if (pce->pce_address.header.type != 0)
|
||||
vty_out(vty, " pce address %s\n",
|
||||
inet_ntoa(pce->pce_address.address.value));
|
||||
if (OspfRI.pce_info.enabled) {
|
||||
|
||||
if (pce->pce_cap_flag.header.type != 0)
|
||||
vty_out(vty, " pce flag 0x%x\n",
|
||||
ntohl(pce->pce_cap_flag.value));
|
||||
if (pce->pce_address.header.type != 0)
|
||||
vty_out(vty, " pce address %s\n",
|
||||
inet_ntoa(pce->pce_address.address.value));
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
|
||||
if (domain->header.type != 0) {
|
||||
if (domain->type == PCE_DOMAIN_TYPE_AREA) {
|
||||
tmp.s_addr = domain->value;
|
||||
vty_out(vty, " pce domain area %s\n",
|
||||
inet_ntoa(tmp));
|
||||
} else {
|
||||
vty_out(vty, " pce domain as %d\n",
|
||||
ntohl(domain->value));
|
||||
}
|
||||
if (pce->pce_cap_flag.header.type != 0)
|
||||
vty_out(vty, " pce flag 0x%x\n",
|
||||
ntohl(pce->pce_cap_flag.value));
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pce->pce_domain, node, domain)) {
|
||||
if (domain->header.type != 0) {
|
||||
if (domain->type == PCE_DOMAIN_TYPE_AREA) {
|
||||
tmp.s_addr = domain->value;
|
||||
vty_out(vty, " pce domain area %s\n",
|
||||
inet_ntoa(tmp));
|
||||
} else {
|
||||
vty_out(vty, " pce domain as %d\n",
|
||||
ntohl(domain->value));
|
||||
}
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
|
||||
if (neighbor->header.type != 0) {
|
||||
if (neighbor->type == PCE_DOMAIN_TYPE_AREA) {
|
||||
tmp.s_addr = neighbor->value;
|
||||
vty_out(vty, " pce neighbor area %s\n",
|
||||
inet_ntoa(tmp));
|
||||
} else {
|
||||
vty_out(vty, " pce neighbor as %d\n",
|
||||
ntohl(neighbor->value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pce->pce_scope.header.type != 0)
|
||||
vty_out(vty, " pce scope 0x%x\n",
|
||||
ntohl(OspfRI.pce_info.pce_scope.value));
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pce->pce_neighbor, node, neighbor)) {
|
||||
if (neighbor->header.type != 0) {
|
||||
if (neighbor->type == PCE_DOMAIN_TYPE_AREA) {
|
||||
tmp.s_addr = neighbor->value;
|
||||
vty_out(vty, " pce neighbor area %s\n",
|
||||
inet_ntoa(tmp));
|
||||
} else {
|
||||
vty_out(vty, " pce neighbor as %d\n",
|
||||
ntohl(neighbor->value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pce->pce_scope.header.type != 0)
|
||||
vty_out(vty, " pce scope 0x%x\n",
|
||||
ntohl(OspfRI.pce_info.pce_scope.value));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1539,7 +1854,7 @@ DEFUN (show_ip_opsf_router_info_pce,
|
||||
struct ri_pce_subtlv_domain *domain;
|
||||
struct ri_pce_subtlv_neighbor *neighbor;
|
||||
|
||||
if (OspfRI.enabled) {
|
||||
if ((OspfRI.enabled) && (OspfRI.pce_info.enabled)) {
|
||||
vty_out(vty, "--- PCE parameters ---\n");
|
||||
|
||||
if (pce->pce_address.header.type != 0)
|
||||
@ -1568,7 +1883,7 @@ DEFUN (show_ip_opsf_router_info_pce,
|
||||
|
||||
} else {
|
||||
vty_out(vty,
|
||||
" Router Information is disabled on this router\n");
|
||||
" PCE info is disabled on this router\n");
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
@ -1,11 +1,13 @@
|
||||
/*
|
||||
* This is an implementation of RFC4970 Router Information
|
||||
* with support of RFC5088 PCE Capabilites announcement
|
||||
* and support of draft-ietf-ospf-segment-routing-extensions-18
|
||||
* for Segment Routing Capabilities announcement
|
||||
*
|
||||
*
|
||||
* Module name: Router Information
|
||||
* Version: 0.99.22
|
||||
* Created: 2012-02-01 by Olivier Dugeon
|
||||
* Copyright (C) 2012 Orange Labs http://www.orange.com/
|
||||
* Author: Olivier Dugeon <olivier.dugeon@orange.com>
|
||||
* Copyright (C) 2012 - 2017 Orange Labs http://www.orange.com/
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
@ -33,7 +35,7 @@
|
||||
*
|
||||
* 24 16 8 0
|
||||
* +--------+--------+--------+--------+
|
||||
* | 1 | MBZ |........|........|
|
||||
* | 4 | MBZ |........|........|
|
||||
* +--------+--------+--------+--------+
|
||||
* |<-Type->|<Resv'd>|<-- Instance --->|
|
||||
*
|
||||
@ -57,9 +59,8 @@
|
||||
* +--------+--------+--------+--------+ |
|
||||
* | LS checksum | Length | V
|
||||
* +--------+--------+--------+--------+ ---
|
||||
* | Type | Length | A
|
||||
* +--------+--------+--------+--------+ | TLV part for Router Information;
|
||||
* Values might be
|
||||
* | Type | Length | A TLV part for Router Information;
|
||||
* +--------+--------+--------+--------+ | Values might be
|
||||
* | Values ... | V structured as a set of sub-TLVs.
|
||||
* +--------+--------+--------+--------+ ---
|
||||
*/
|
||||
@ -68,9 +69,9 @@
|
||||
* Following section defines TLV body parts.
|
||||
*/
|
||||
|
||||
/* Up to now, 8 code point have been assigned to Router Information */
|
||||
/* Up to now, 11 code points have been assigned to Router Information */
|
||||
/* Only type 1 Router Capabilities and 6 PCE are supported with this code */
|
||||
#define RI_IANA_MAX_TYPE 8
|
||||
#define RI_IANA_MAX_TYPE 11
|
||||
|
||||
/* RFC4970: Router Information Capabilities TLV */ /* Mandatory */
|
||||
#define RI_TLV_CAPABILITIES 1
|
||||
@ -80,12 +81,13 @@ struct ri_tlv_router_cap {
|
||||
u_int32_t value;
|
||||
};
|
||||
|
||||
#define RI_GRACE_RESTART 0x01
|
||||
#define RI_GRACE_HELPER 0x02
|
||||
#define RI_STUB_SUPPORT 0x04
|
||||
#define RI_TE_SUPPORT 0x08
|
||||
#define RI_P2P_OVER_LAN 0x10
|
||||
#define RI_TE_EXPERIMENTAL 0x20
|
||||
/* Capabilities bits are left align */
|
||||
#define RI_GRACE_RESTART 0x80000000
|
||||
#define RI_GRACE_HELPER 0x40000000
|
||||
#define RI_STUB_SUPPORT 0x20000000
|
||||
#define RI_TE_SUPPORT 0x10000000
|
||||
#define RI_P2P_OVER_LAN 0x08000000
|
||||
#define RI_TE_EXPERIMENTAL 0x04000000
|
||||
|
||||
#define RI_TLV_LENGTH 4
|
||||
|
||||
@ -151,22 +153,30 @@ struct ri_pce_subtlv_neighbor {
|
||||
#define RI_PCE_SUBTLV_CAP_FLAG 5
|
||||
|
||||
#define PCE_CAP_GMPLS_LINK 0x0001
|
||||
#define PCE_CAP_BIDIRECTIONAL 0x0002
|
||||
#define PCE_CAP_DIVERSE_PATH 0x0004
|
||||
#define PCE_CAP_LOAD_BALANCE 0x0008
|
||||
#define PCE_CAP_SYNCHRONIZED 0x0010
|
||||
#define PCE_CAP_BIDIRECTIONAL 0x0002
|
||||
#define PCE_CAP_DIVERSE_PATH 0x0004
|
||||
#define PCE_CAP_LOAD_BALANCE 0x0008
|
||||
#define PCE_CAP_SYNCHRONIZED 0x0010
|
||||
#define PCE_CAP_OBJECTIVES 0x0020
|
||||
#define PCE_CAP_ADDITIVE 0x0040
|
||||
#define PCE_CAP_PRIORIZATION 0x0080
|
||||
#define PCE_CAP_MULTIPLE_REQ 0x0100
|
||||
#define PCE_CAP_PRIORIZATION 0x0080
|
||||
#define PCE_CAP_MULTIPLE_REQ 0x0100
|
||||
|
||||
struct ri_pce_subtlv_cap_flag {
|
||||
struct tlv_header header; /* Type = 5; Length = n x 4 bytes. */
|
||||
u_int32_t value;
|
||||
};
|
||||
|
||||
/* Structure to share flooding scope info for Segment Routing */
|
||||
struct scope_info {
|
||||
u_int8_t scope;
|
||||
struct in_addr area_id;
|
||||
};
|
||||
|
||||
/* Prototypes. */
|
||||
extern int ospf_router_info_init(void);
|
||||
extern void ospf_router_info_term(void);
|
||||
|
||||
extern int ospf_router_info_enable(void);
|
||||
extern void ospf_router_info_update_sr(bool, struct sr_srgb, u_int8_t);
|
||||
extern struct scope_info ospf_router_info_get_flooding_scope(void);
|
||||
#endif /* _ZEBRA_OSPF_ROUTER_INFO_H */
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "ospfd/ospf_ase.h"
|
||||
#include "ospfd/ospf_abr.h"
|
||||
#include "ospfd/ospf_dump.h"
|
||||
#include "ospfd/ospf_sr.h"
|
||||
|
||||
/* Variables to ensure a SPF scheduled log message is printed only once */
|
||||
|
||||
@ -1339,7 +1340,6 @@ static int ospf_spf_calculate_timer(struct thread *thread)
|
||||
|
||||
ospf_ase_calculate_timer_add(ospf);
|
||||
|
||||
|
||||
if (IS_DEBUG_OSPF_EVENT)
|
||||
zlog_debug("%s: ospf install new route, vrf %s id %u new_table count %lu",
|
||||
__PRETTY_FUNCTION__,
|
||||
@ -1366,6 +1366,9 @@ static int ospf_spf_calculate_timer(struct thread *thread)
|
||||
ospf_abr_task(ospf);
|
||||
abr_time = monotime_since(&start_time, NULL);
|
||||
|
||||
/* Schedule Segment Routing update */
|
||||
ospf_sr_update_timer_add(ospf);
|
||||
|
||||
total_spf_time =
|
||||
monotime_since(&spf_start_time, &ospf->ts_spf_duration);
|
||||
|
||||
|
2186
ospfd/ospf_sr.c
Normal file
2186
ospfd/ospf_sr.c
Normal file
File diff suppressed because it is too large
Load Diff
315
ospfd/ospf_sr.h
Normal file
315
ospfd/ospf_sr.h
Normal file
@ -0,0 +1,315 @@
|
||||
/*
|
||||
* This is an implementation of Segment Routing
|
||||
* as per draft draft-ietf-ospf-segment-routing-extensions-24
|
||||
*
|
||||
* Module name: Segment Routing header definitions
|
||||
*
|
||||
* Author: Olivier Dugeon <olivier.dugeon@orange.com>
|
||||
* Author: Anselme Sawadogo <anselmesawadogo@gmail.com>
|
||||
*
|
||||
* Copyright (C) 2016 - 2017 Orange Labs http://www.orange.com
|
||||
*
|
||||
* This file is part of FRR.
|
||||
*
|
||||
* FRR is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* FRR is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with FRR; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _FRR_OSPF_SR_H
|
||||
#define _FRR_OSPF_SR_H
|
||||
|
||||
/* Default Route priority for OSPF Segment Routing */
|
||||
#define OSPF_SR_PRIORITY_DEFAULT 10
|
||||
|
||||
/* macros and constants for segment routing */
|
||||
#define SET_RANGE_SIZE_MASK 0xffffff00
|
||||
#define GET_RANGE_SIZE_MASK 0x00ffffff
|
||||
#define SET_LABEL_MASK 0xffffff00
|
||||
#define GET_LABEL_MASK 0x00ffffff
|
||||
#define SET_RANGE_SIZE(range_size) ((range_size << 8) & SET_RANGE_SIZE_MASK)
|
||||
#define GET_RANGE_SIZE(range_size) ((range_size >> 8) & GET_RANGE_SIZE_MASK)
|
||||
#define SET_LABEL(label) ((label << 8) & SET_LABEL_MASK)
|
||||
#define GET_LABEL(label) ((label >> 8) & GET_LABEL_MASK)
|
||||
|
||||
/* Label range for Adj-SID attribution purpose. See ospf_ext.c */
|
||||
#define ADJ_SID_MIN 50000
|
||||
#define ADJ_SID_MAX 51000
|
||||
|
||||
#define OSPF_SR_DEFAULT_METRIC 1
|
||||
|
||||
/* Segment Routing TLVs as per draft-ietf-ospf-segment-routing-extensions-19 */
|
||||
|
||||
/* Segment ID could be a Label (3 bytes) or an Index (4 bytes) */
|
||||
#define SID_BASE_SIZE 4
|
||||
#define SID_LABEL 3
|
||||
#define SID_LABEL_SIZE (SID_BASE_SIZE + SID_LABEL)
|
||||
#define SID_INDEX 4
|
||||
#define SID_INDEX_SIZE (SID_BASE_SIZE + SID_INDEX)
|
||||
|
||||
/* SID/Label Sub TLV - section 2.1 */
|
||||
#define SUBTLV_SID_LABEL 1
|
||||
#define SUBTLV_SID_LABEL_SIZE 8
|
||||
struct subtlv_sid_label {
|
||||
/* Length is 3 (20 rightmost bits MPLS label) or 4 (32 bits SID) */
|
||||
struct tlv_header header;
|
||||
u_int32_t value;
|
||||
};
|
||||
|
||||
/*
|
||||
* Following section defines Segment Routing TLV (tag, length, value)
|
||||
* structures, used in Router Information Opaque LSA.
|
||||
*/
|
||||
|
||||
/* RI SR-Algorithm TLV - section 3.1 */
|
||||
#define RI_SR_TLV_SR_ALGORITHM 8
|
||||
struct ri_sr_tlv_sr_algorithm {
|
||||
struct tlv_header header;
|
||||
#define SR_ALGORITHM_SPF 0
|
||||
#define SR_ALGORITHM_STRICT_SPF 1
|
||||
#define SR_ALGORITHM_UNSET 255
|
||||
#define ALGORITHM_COUNT 4
|
||||
/* Only 4 algorithms supported in this code */
|
||||
u_int8_t value[ALGORITHM_COUNT];
|
||||
};
|
||||
|
||||
/* RI SID/Label Range TLV - section 3.2 */
|
||||
#define RI_SR_TLV_SID_LABEL_RANGE 9
|
||||
struct ri_sr_tlv_sid_label_range {
|
||||
struct tlv_header header;
|
||||
/* Only 24 upper most bits are significant */
|
||||
#define SID_RANGE_LABEL_LENGTH 3
|
||||
u_int32_t size;
|
||||
/* A SID/Label sub-TLV will follow. */
|
||||
struct subtlv_sid_label lower;
|
||||
};
|
||||
|
||||
/* RI Node/MSD TLV as per draft-ietf-ospf-segment-routing-msd-05 */
|
||||
#define RI_SR_TLV_NODE_MSD 12
|
||||
struct ri_sr_tlv_node_msd {
|
||||
struct tlv_header header;
|
||||
u_int8_t subtype; /* always = 1 */
|
||||
u_int8_t value;
|
||||
u_int16_t padding;
|
||||
};
|
||||
|
||||
/*
|
||||
* Following section defines Segment Routing TLV (tag, length, value)
|
||||
* structures, used in Extended Prefix/Link Opaque LSA.
|
||||
*/
|
||||
|
||||
/* Adj-SID and LAN-Ajd-SID subtlvs' flags */
|
||||
#define EXT_SUBTLV_LINK_ADJ_SID_BFLG 0x80
|
||||
#define EXT_SUBTLV_LINK_ADJ_SID_VFLG 0x40
|
||||
#define EXT_SUBTLV_LINK_ADJ_SID_LFLG 0x20
|
||||
#define EXT_SUBTLV_LINK_ADJ_SID_SFLG 0x10
|
||||
|
||||
/* Prefix SID subtlv Flags */
|
||||
#define EXT_SUBTLV_PREFIX_SID_NPFLG 0x40
|
||||
#define EXT_SUBTLV_PREFIX_SID_MFLG 0x20
|
||||
#define EXT_SUBTLV_PREFIX_SID_EFLG 0x10
|
||||
#define EXT_SUBTLV_PREFIX_SID_VFLG 0x08
|
||||
#define EXT_SUBTLV_PREFIX_SID_LFLG 0x04
|
||||
|
||||
/* SID/Label Binding subtlv Flags */
|
||||
#define EXT_SUBTLV_SID_BINDING_MFLG 0x80
|
||||
|
||||
/* Extended Prefix Range TLV - section 4 */
|
||||
#define EXT_TLV_PREF_RANGE 2
|
||||
#define EXT_SUBTLV_PREFIX_RANGE_SIZE 12
|
||||
struct ext_tlv_prefix_range {
|
||||
struct tlv_header header;
|
||||
u_int8_t pref_length;
|
||||
u_int8_t af;
|
||||
u_int16_t range_size;
|
||||
u_int8_t flags;
|
||||
u_int8_t reserved[3];
|
||||
struct in_addr address;
|
||||
};
|
||||
|
||||
/* Prefix SID Sub-TLV - section 5 */
|
||||
#define EXT_SUBTLV_PREFIX_SID 2
|
||||
#define EXT_SUBTLV_PREFIX_SID_SIZE 8
|
||||
struct ext_subtlv_prefix_sid {
|
||||
struct tlv_header header;
|
||||
u_int8_t flags;
|
||||
u_int8_t reserved;
|
||||
u_int8_t mtid;
|
||||
u_int8_t algorithm;
|
||||
u_int32_t value;
|
||||
};
|
||||
|
||||
/* Adj-SID Sub-TLV - section 6.1 */
|
||||
#define EXT_SUBTLV_ADJ_SID 2
|
||||
#define EXT_SUBTLV_ADJ_SID_SIZE 8
|
||||
struct ext_subtlv_adj_sid {
|
||||
struct tlv_header header;
|
||||
u_int8_t flags;
|
||||
u_int8_t reserved;
|
||||
u_int8_t mtid;
|
||||
u_int8_t weight;
|
||||
u_int32_t value;
|
||||
};
|
||||
|
||||
/* LAN Adj-SID Sub-TLV - section 6.2 */
|
||||
#define EXT_SUBTLV_LAN_ADJ_SID 3
|
||||
#define EXT_SUBTLV_LAN_ADJ_SID_SIZE 12
|
||||
struct ext_subtlv_lan_adj_sid {
|
||||
struct tlv_header header;
|
||||
u_int8_t flags;
|
||||
u_int8_t reserved;
|
||||
u_int8_t mtid;
|
||||
u_int8_t weight;
|
||||
struct in_addr neighbor_id;
|
||||
u_int32_t value;
|
||||
};
|
||||
|
||||
/*
|
||||
* Following section define structure used to manage Segment Routing
|
||||
* information and TLVs / SubTLVs
|
||||
*/
|
||||
|
||||
/* Structure aggregating SRGB info retrieved from an lsa */
|
||||
struct sr_srgb {
|
||||
u_int32_t range_size;
|
||||
u_int32_t lower_bound;
|
||||
};
|
||||
|
||||
/* SID type to make difference between loopback interfaces and others */
|
||||
enum sid_type { PREF_SID, ADJ_SID, LAN_ADJ_SID };
|
||||
|
||||
/* Structure aggregating all OSPF Segment Routing information for the node */
|
||||
struct ospf_sr_db {
|
||||
/* Status of Segment Routing: enable or disable */
|
||||
bool enabled;
|
||||
|
||||
/* Ongoing Update following an OSPF SPF */
|
||||
bool update;
|
||||
|
||||
/* Flooding Scope: Area = 10 or AS = 11 */
|
||||
u_int8_t scope;
|
||||
|
||||
/* FRR SR node */
|
||||
struct sr_node *self;
|
||||
|
||||
/* List of neighbour SR nodes */
|
||||
struct hash *neighbors;
|
||||
|
||||
/* List of SR prefix */
|
||||
struct route_table *prefix;
|
||||
|
||||
/* Local SR info announced in Router Info LSA */
|
||||
|
||||
/* Algorithms supported by the node */
|
||||
u_int8_t algo[ALGORITHM_COUNT];
|
||||
/*
|
||||
* Segment Routing Global Block i.e. label range
|
||||
* Only one range supported in this code
|
||||
*/
|
||||
struct sr_srgb srgb;
|
||||
/* Maximum SID Depth supported by the node */
|
||||
u_int8_t msd;
|
||||
};
|
||||
|
||||
/* Structure aggregating all received SR info from LSAs by node */
|
||||
struct sr_node {
|
||||
struct in_addr adv_router; /* used to identify sender of LSA */
|
||||
/* 24-bit Opaque-ID field value according to RFC 7684 specification */
|
||||
u_int32_t instance;
|
||||
|
||||
u_int8_t algo[ALGORITHM_COUNT]; /* Algorithms supported by the node */
|
||||
/* Segment Routing Global Block i.e. label range */
|
||||
struct sr_srgb srgb;
|
||||
u_int8_t msd; /* Maximum SID Depth */
|
||||
|
||||
/* List of Prefix & Link advertise by this node */
|
||||
struct list *ext_prefix; /* For Node SID */
|
||||
struct list *ext_link; /* For Adj and LAN SID */
|
||||
|
||||
/* Pointer to FRR SR-Node or NULL if it is not a neighbor */
|
||||
struct sr_node *neighbor;
|
||||
};
|
||||
|
||||
|
||||
/* Segment Routing - NHLFE info: support IPv4 Only */
|
||||
struct sr_nhlfe {
|
||||
struct prefix_ipv4 prefv4;
|
||||
struct in_addr nexthop;
|
||||
ifindex_t ifindex;
|
||||
mpls_label_t label_in;
|
||||
mpls_label_t label_out;
|
||||
};
|
||||
|
||||
/* Structure aggregating all Segment Routing Link information */
|
||||
/* Link are generally advertised by pair: primary + backup */
|
||||
struct sr_link {
|
||||
struct in_addr adv_router; /* used to identify sender of LSA */
|
||||
/* 24-bit Opaque-ID field value according to RFC 7684 specification */
|
||||
u_int32_t instance;
|
||||
|
||||
/* Flags to manage this link parameters. */
|
||||
u_int32_t flags[2];
|
||||
|
||||
/* Segment Routing ID */
|
||||
u_int32_t sid[2];
|
||||
enum sid_type type;
|
||||
|
||||
/* SR NHLFE for this link */
|
||||
struct sr_nhlfe nhlfe[2];
|
||||
|
||||
/* Back pointer to SR Node which advertise this Link */
|
||||
struct sr_node *srn;
|
||||
};
|
||||
|
||||
/* Structure aggregating all Segment Routing Prefix information */
|
||||
struct sr_prefix {
|
||||
struct in_addr adv_router; /* used to identify sender of LSA */
|
||||
/* 24-bit Opaque-ID field value according to RFC 7684 specification */
|
||||
u_int32_t instance;
|
||||
|
||||
/* Flags to manage this prefix parameters. */
|
||||
u_int32_t flags;
|
||||
|
||||
/* Segment Routing ID */
|
||||
u_int32_t sid;
|
||||
enum sid_type type;
|
||||
|
||||
/* SR NHLFE for this prefix */
|
||||
struct sr_nhlfe nhlfe;
|
||||
|
||||
/* Back pointer to SR Node which advertise this Prefix */
|
||||
struct sr_node *srn;
|
||||
|
||||
/* Pointer to SR Node which is the next hop for this Prefix
|
||||
* or NULL if next hop is the destination of the prefix */
|
||||
struct sr_node *nexthop;
|
||||
};
|
||||
|
||||
/* Prototypes definition */
|
||||
/* Segment Routing initialisation functions */
|
||||
extern int ospf_sr_init(void);
|
||||
extern void ospf_sr_term(void);
|
||||
/* Segment Routing LSA update & delete functions */
|
||||
extern void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa);
|
||||
extern void ospf_sr_ri_lsa_delete(struct ospf_lsa *lsa);
|
||||
extern void ospf_sr_ext_link_lsa_update(struct ospf_lsa *);
|
||||
extern void ospf_sr_ext_link_lsa_delete(struct ospf_lsa *);
|
||||
extern void ospf_sr_ext_prefix_lsa_update(struct ospf_lsa *);
|
||||
extern void ospf_sr_ext_prefix_lsa_delete(struct ospf_lsa *);
|
||||
/* Segment Routing configuration functions */
|
||||
extern u_int32_t get_ext_link_label_value(void);
|
||||
extern void ospf_sr_config_write_router(struct vty *);
|
||||
/* Segment Routing re-routing function */
|
||||
extern void ospf_sr_update_timer_add(struct ospf *);
|
||||
#endif /* _FRR_OSPF_SR_H */
|
@ -240,6 +240,7 @@ struct ospf {
|
||||
struct thread *t_external_lsa; /* AS-external-LSA origin timer. */
|
||||
struct thread
|
||||
*t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */
|
||||
struct thread *t_sr_update; /* Segment Routing update timer */
|
||||
|
||||
unsigned int maxage_delay; /* Delay on Maxage remover timer, sec */
|
||||
struct thread *t_maxage; /* MaxAge LSA remover timer. */
|
||||
|
@ -20,6 +20,7 @@ ospfd_libfrrospf_a_SOURCES = \
|
||||
ospfd/ospf_bfd.c \
|
||||
ospfd/ospf_dump.c \
|
||||
ospfd/ospf_dump_api.c \
|
||||
ospfd/ospf_ext.c \
|
||||
ospfd/ospf_flood.c \
|
||||
ospfd/ospf_ia.c \
|
||||
ospfd/ospf_interface.c \
|
||||
@ -36,6 +37,7 @@ ospfd_libfrrospf_a_SOURCES = \
|
||||
ospfd/ospf_route.c \
|
||||
ospfd/ospf_routemap.c \
|
||||
ospfd/ospf_spf.c \
|
||||
ospfd/ospf_sr.c \
|
||||
ospfd/ospf_te.c \
|
||||
ospfd/ospf_vty.c \
|
||||
ospfd/ospf_zebra.c \
|
||||
@ -66,6 +68,7 @@ noinst_HEADERS += \
|
||||
ospfd/ospf_apiserver.h \
|
||||
ospfd/ospf_ase.h \
|
||||
ospfd/ospf_bfd.h \
|
||||
ospfd/ospf_ext.h \
|
||||
ospfd/ospf_flood.h \
|
||||
ospfd/ospf_ia.h \
|
||||
ospfd/ospf_interface.h \
|
||||
@ -76,6 +79,7 @@ noinst_HEADERS += \
|
||||
ospfd/ospf_ri.h \
|
||||
ospfd/ospf_route.h \
|
||||
ospfd/ospf_spf.h \
|
||||
ospfd/ospf_sr.h \
|
||||
ospfd/ospf_te.h \
|
||||
ospfd/ospf_vty.h \
|
||||
ospfd/ospf_zebra.h \
|
||||
|
@ -75,6 +75,7 @@ vtysh_scan += $(top_srcdir)/ospfd/ospf_opaque.c
|
||||
vtysh_scan += $(top_srcdir)/ospfd/ospf_ri.c
|
||||
vtysh_scan += $(top_srcdir)/ospfd/ospf_routemap.c
|
||||
vtysh_scan += $(top_srcdir)/ospfd/ospf_te.c
|
||||
vtysh_scan += $(top_srcdir)/ospfd/ospf_sr.c
|
||||
vtysh_scan += $(top_srcdir)/ospfd/ospf_vty.c
|
||||
endif
|
||||
|
||||
|
@ -102,6 +102,7 @@ static const struct message rtproto_str[] = {
|
||||
{RTPROT_MROUTED, "mroute"},
|
||||
{RTPROT_BGP, "BGP"},
|
||||
{RTPROT_OSPF, "OSPF"},
|
||||
{RTPROT_OSPF_SR, "OSPF-SR"},
|
||||
{RTPROT_ISIS, "IS-IS"},
|
||||
{RTPROT_RIP, "RIP"},
|
||||
{RTPROT_RIPNG, "RIPNG"},
|
||||
|
@ -98,7 +98,8 @@ static inline int is_selfroute(int proto)
|
||||
|| (proto == RTPROT_ISIS) || (proto == RTPROT_RIPNG)
|
||||
|| (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP)
|
||||
|| (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)
|
||||
|| (proto == RTPROT_RIP) || (proto == RTPROT_SHARP)) {
|
||||
|| (proto == RTPROT_RIP) || (proto == RTPROT_SHARP)
|
||||
|| (proto == RTPROT_OSPF_SR)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -118,6 +119,9 @@ static inline int zebra2proto(int proto)
|
||||
case ZEBRA_ROUTE_OSPF6:
|
||||
proto = RTPROT_OSPF;
|
||||
break;
|
||||
case ZEBRA_ROUTE_OSPF_SR:
|
||||
proto = RTPROT_OSPF_SR;
|
||||
break;
|
||||
case ZEBRA_ROUTE_STATIC:
|
||||
proto = RTPROT_STATIC;
|
||||
break;
|
||||
|
@ -52,6 +52,7 @@
|
||||
#define RTPROT_EIGRP 192
|
||||
#define RTPROT_LDP 193
|
||||
#define RTPROT_SHARP 194
|
||||
#define RTPROT_OSPF_SR 195
|
||||
|
||||
void rt_netlink_init(void);
|
||||
|
||||
|
@ -316,6 +316,12 @@ void mpls_ldp_lsp_uninstall_all(struct hash_backet *backet, void *ctxt);
|
||||
*/
|
||||
void mpls_ldp_ftn_uninstall_all(struct zebra_vrf *zvrf, int afi);
|
||||
|
||||
/*
|
||||
* Uninstall all Segment Routing NHLFEs for a particular LSP forwarding entry.
|
||||
* If no other NHLFEs exist, the entry would be deleted.
|
||||
*/
|
||||
void mpls_sr_lsp_uninstall_all(struct hash_backet *backet, void *ctxt);
|
||||
|
||||
#if defined(HAVE_CUMULUS)
|
||||
/*
|
||||
* Check that the label values used in LSP creation are consistent. The
|
||||
@ -448,6 +454,8 @@ static inline int re_type_from_lsp_type(enum lsp_types_t lsp_type)
|
||||
return ZEBRA_ROUTE_LDP;
|
||||
case ZEBRA_LSP_BGP:
|
||||
return ZEBRA_ROUTE_BGP;
|
||||
case ZEBRA_LSP_SR:
|
||||
return ZEBRA_ROUTE_OSPF_SR;
|
||||
case ZEBRA_LSP_NONE:
|
||||
default:
|
||||
return ZEBRA_ROUTE_KERNEL;
|
||||
@ -464,6 +472,8 @@ static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type)
|
||||
return "LDP";
|
||||
case ZEBRA_LSP_BGP:
|
||||
return "BGP";
|
||||
case ZEBRA_LSP_SR:
|
||||
return "SR";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user