OSPF Segment Routing
====================
-This is an EXPERIMENTAL support of draft draft-ietf-ospf-segment-routing-extensions-24.
+This is an EXPERIMENTAL support of draft
+`draft-ietf-ospf-segment-routing-extensions-24`.
DON'T use it for production network.
Implementation details
----------------------
-### Concepts
+
+Concepts
+~~~~~~~~
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 (MSD).
- - Extended Link: flood the Adjaceny and Lan Adjacency Segment Identifier
- - Extended Prefix: flood the Prefix Segment Identifier
+* **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 (MSD).
+* **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
+The implementation follow previous TE and Router Information codes. It used the
+OPAQUE LSA functions defined 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.
+Information LSA s are received.
-### Overview
+Overview
+~~~~~~~~
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.
+
+* 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 of 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 back 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 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 of 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 back 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.
::
| |
+---------------+
- Figure1: Overview of Segment Routing interaction
+ Figure 1: Overview of Segment Routing interaction
+
+Module interactions
+~~~~~~~~~~~~~~~~~~~
+
+To process incoming LSA, the code is based on the capability to call `hook()`
+functions when LSA are inserted or delete to / from the LSDB and the
+possibility to register particular treatment for Opaque LSA. The first point
+is provided by the OSPF API feature and the second by the Opaque implementation
+itself. Indeed, it is possible to register callback function for a given Opaque
+LSA ID (see `ospf_register_opaque_functab()` function defined in
+`ospf_opaque.c`). Each time a new LSA is added to the LSDB, the
+`new_lsa_hook()` function previously register for this LSA type is called. For
+Opaque LSA it is the `ospf_opaque_lsa_install_hook()`. For deletion, it is
+`ospf_opaque_lsa_delete_hook()`.
+
+Note that incoming LSA which is already present in the LSDB will be inserted
+after the old instance of this LSA remove from the LSDB. Thus, after the first
+time, each incoming LSA will trigger a `delete` following by an `install`. This
+is not very helpfull to handle real LSA deletion. In fact, LSA deletion is done
+by Flushing LSA i.e. flood LSA after seting its age to MAX_AGE. Then, a garbage
+function has the role to remove all LSA with `age == MAX_AGE` in the LSDB. So,
+to handle LSA Flush, the best is to look to the LSA age to determine if it is
+an installation or a future deletion i.e. the flushed LSA is first store in the
+LSDB with MAX_AGE waiting for the garbage collector function.
+
+Router Information LSAs
+^^^^^^^^^^^^^^^^^^^^^^^
+
+To activate Segment Routing, new CLI command `segment-routing on` has been
+introduced. When this command is activated, function
+`ospf_router_info_update_sr()` is called to indicate to Router Information
+process that Segment Routing TLVs must be flood. Same function is called to
+modify the Segment Routing Global Block (SRGB) and Maximum Stack Depth (MSD)
+TLV. Only Shortest Path First (SPF) Algorithm is supported, so no possiblity
+to modify this TLV is offer by the code.
+
+When Opaque LSA Tyep 4 i.e. Router Information are stored in LSDB, function
+`ospf_opaque_lsa_install_hook()` will call the previously registered function
+`ospf_router_info_lsa_update()`. In turn, the function will simply trigger
+`ospf_sr_ri_lsa_update()` or `ospf_sr_ri_lsa_delete` in function of the LSA
+age. Before, it verifies that the LSA Opaque Type is 4 (Router Information).
+Self Opaque LSA are not send back to the Segment Routing functions as
+information are already stored.
+
+Extended Link Prefix LSAs
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Like for Router Information, Segment Routing is activate at the Extended
+Link/Prefix level with new `segment-routing on` command. This trigger
+automtically the flooding of Extended Link LSA for all ospf interface where
+adjacency is full. For Extended Prefix LSA, the new CLI command
+`segment-routing prefix ...` will trigger the flooding of Prefix SID
+TLV/SubTLVs.
+
+When Opaque LSA Type 7 i.e. Extended Prefix and Type 8 i.e. Extended Link are
+store in the LSDB, `ospf_ext_pref_update_lsa()` respectively
+`ospf_ext_link_update_lsa()` are called like for Router Information LSA. In
+turn, they respectively trigger `ospf_sr_ext_prefix_lsa_update()` /
+`ospf_sr_ext_link_lsa_update()` or `ospf_sr_ext_prefix_lsa_delete()` /
+`ospf_sr_ext_link_lsa_delete()` if the LSA age is equal to MAX_AGE.
+
+Zebra
+^^^^^
+
+When a new MPLS entry or new Forwarding Equivalent Class (FEC) must be added or
+deleted in the data plane, `add_sid_nhlfe()` respectively `del_sid_nhlfe()` are
+called. Once check the validity of labels, they are send to ZEBRA layer through
+`ZEBRA_MPLS_LABELS_ADD` command, respectively `ZEBRA_MPLS_LABELS_DELETE`
+command for deletion. This is completed by a new labelled route through
+`ZEBRA_ROUTE_ADD` command, respectively `ZEBRA_ROUTE_DELETE` command.
-### Module interactions
+Configuration
+-------------
-To process incoming LSA, the code is based on the capability to call `hook()` functions when LSA are inserted or delete to / from the LSDB and the possibility to register particular treatment for Opaque LSA. The first point is provided by the OSPF API feature and the second by the Opaque implementation itself. Indeed, it is possible to register callback function for a given Opaque LSA ID (see `ospf_register_opaque_functab()` function defined in `ospf_opaque.c`). Each time a new LSA is added to the LSDB, the `new_lsa_hook()` function previously register for this LSA type is called. For Opaque LSA it is the `ospf_opaque_lsa_install_hook()`. For deletion, it is `ospf_opaque_lsa_delete_hook()`.
+Linux Kernel
+~~~~~~~~~~~~
-Note that incoming LSA which is already present in the LSDB will be inserted after the old instance of this LSA remove from the LSDB. Thus, after the first time, each incoming LSA will trigger a `delete` following by an `install`. This is not very helpfull to handle real LSA deletion. In fact, LSA deletion is done by Flushing LSA i.e. flood LSA after seting its age to MAX_AGE. Then, a garbage function has the role to remove all LSA with `age == MAX_AGE` in the LSDB. So, to handle LSA Flush, the best is to look to the LSA age to determine if it is an installation or a future deletion i.e. the flushed LSA is first store in the LSDB with MAX_AGE waiting for the garbage collector function.
+In order to use OSPF Segment Routing, you must setup MPLS data plane. Up to
+know, only Linux Kernel version >= 4.5 is supported.
-#### Router Information LSAs
+First, the MPLS modules aren't loaded by default, so you'll need to load them
+yourself:
-To activate Segment Routing, new CLI command `segment-routing on` has been introduced. When this command is activated, function `ospf_router_info_update_sr()` is called to indicate to Router Information process that Segment Routing TLVs must be flood. Same function is called to modify the Segment Routing Global Block (SRGB) and Maximum Stack Depth (MSD) TLV. Only Shortest Path First (SPF) Algorithm is supported, so no possiblity to modify this TLV is offer by the code.
+::
-When Opaque LSA Tyep 4 i.e. Router Information are stored in LSDB, function `ospf_opaque_lsa_install_hook()` will call the previously registered function `ospf_router_info_lsa_update()`. In turn, the function will simply trigger `ospf_sr_ri_lsa_update()` or `ospf_sr_ri_lsa_delete` in function of the LSA age. Before, it verifies that the LSA Opaque Type is 4 (Router Information). Self Opaque LSA are not send back to the Segment Routing functions as information are already stored.
+ modprobe mpls_router
+ modprobe mpls_gso
+ modprobe mpls_iptunnel
-#### Extended Link Prefix LSAs
+Then, you must activate MPLS on the interface you would used:
-Like for Router Information, Segment Routing is activate at the Extended Link/Prefix level with new `segment-routing on` command. This trigger automtically the flooding of Extended Link LSA for all ospf interface where adjacency is full. For Extended Prefix LSA, the new CLI command `segment-routing prefix ...` will trigger the flooding of Prefix SID TLV/SubTLVs.
+::
-When Opaque LSA Type 7 i.e. Extended Prefix and Type 8 i.e. Extended Link are store in the LSDB, `ospf_ext_pref_update_lsa()` respectively `ospf_ext_link_update_lsa()` are called like for Router Information LSA. In turn, they respectively trigger `ospf_sr_ext_prefix_lsa_update()` / `ospf_sr_ext_link_lsa_update()` or `ospf_sr_ext_prefix_lsa_delete()` / `ospf_sr_ext_link_lsa_delete()` if the LSA age is equel to MAX_AGE.
+ sysctl -w net.mpls.conf.enp0s9.input=1
+ sysctl -w net.mpls.conf.lo.input=1
+ sysctl -w net.mpls.platform_labels=1048575
-#### Zebra
+The last line fix the maximum MPLS label value.
-When a new MPLS entry of new Forwarding Equivalent Class (FEC) must be add or delete in the data plane, `add_sid_nhlfe()` respectively `del_sid_nhlfe()` are called. Once check the validity of labels, they send to ZEBRA layer a new labels through `ZEBRA_MPLS_LABELS_ADD` command, respectively `ZEBRA_MPLS_LABELS_DELETE` command for deletion. This is completed by a new labelled route through `ZEBRA_ROUTE_ADD` command, respectively `ZEBRA_ROUTE_DELETE` command.
+Once OSPFd start with Segment Routing, you could check that MPLS routes are
+enable with:
-Configuration
--------------
+::
+
+ ip -M route
+ ip route
+
+The first command show the MPLS LFIB table while the second show the FIB
+table which contains route with MPLS label encapsulation.
+
+If you disable Penultimate Hop Popping with the `no-php-flag` (see below), you
+MUST check that RP filter is not enable for the interface you intend to use,
+especially the `lo` one. For that purpose, disable RP filtering with:
+
+::
+
+ systcl -w net.ipv4.conf.all.rp_filter=0
+ sysctl -w net.ipv4.conf.lo.rp_filter=0
+
+OSPFd
+~~~~~
Here it is a simple example of configuration to enable Segment Routing. Note
-that ``opaque capability`` must be set to activate Opaque LSA prior to Segment
+that `opaque capability` and `router information` must be set to activate
+Opaque LSA prior to Segment
Routing.
::
- router ospf
- ospf router-id 192.168.1.11
- capability opaque
- mpls-te on
- mpls-te router-address 192.168.1.11
- router-info area 0.0.0.0
- segment-routing on
- segment-routing global-block 10000 19999
- segment-routing node-msd 8
- segment-routing prefix 192.168.1.11/32 index 1100
+ router ospf
+ ospf router-id 192.168.1.11
+ capability opaque
+ mpls-te on
+ mpls-te router-address 192.168.1.11
+ router-info area 0.0.0.0
+ segment-routing on
+ segment-routing global-block 10000 19999
+ segment-routing node-msd 8
+ segment-routing prefix 192.168.1.11/32 index 1100
The first segment-routing statement enable it. The Second one set the SRGB,
-third line the MSD and finally, set the Prefix SID index for tha given prefix.
+third line the MSD and finally, set the Prefix SID index for a given prefix.
Note that only prefix of Loopback interface could be configured with a Prefix
-SID.
+SID. It is possible to add `no-php-flag` at the end of the prefix command to
+disbale Penultimate Hop Popping. This advertises peers that they MUST NOT pop
+the MPLS label prior to sending the packet.
Known limitations
-----------------
- - Runs only within default VRF
- - Only single Area is supported. ABR is not yet supported
- - Only SPF algorithm is supported
- - Extended Prefix Range is not supported
- - MPLS table are not flush at startup. Thus, restarting zebra process is mandatory to remove old MPLS entries in the data plane after a crash of ospfd daemon.
+* Runs only within default VRF
+* Only single Area is supported. ABR is not yet supported
+* Only SPF algorithm is supported
+* Extended Prefix Range is not supported
+* MPLS table are not flush at startup. Thus, restarting zebra process is
+ mandatory to remove old MPLS entries in the data plane after a crash of
+ ospfd daemon
+* Due to a bug in OSPF Opaque, LSA are not flood when enable Segment Routing
+ through CLI once OSPFd started. You must configure Segment Routing within
+ configuration file before launching OSPFd
+* With NO Penultimate Hop Popping, it is not possible to express a Segment
+ Path with an Adjacency SID due to the impossibility for the Linux Kernel to
+ perform double POP instruction.
Credits
-------
- * Author: Anselme Sawadogo <anselmesawadogo@gmail.com>
- * Author: Olivier Dugeon <olivier.dugeon@orange.com>
- * Copyright (C) 2016 - 2018 Orange Labs http://www.orange.com
+
+* Author: Anselme Sawadogo <anselmesawadogo@gmail.com>
+* Author: Olivier Dugeon <olivier.dugeon@orange.com>
+* Copyright (C) 2016 - 2018 Orange Labs http://www.orange.com
This work has been performed in the framework of the H2020-ICT-2014
project 5GEx (Grant Agreement no. 671636), which is partially funded
@section Segment Routing
This is an EXPERIMENTAL support of Segment Routing as per draft
- draft-ietf-ospf-segment-routing-extensions-24i for MPLS dataplane.
+ draft-ietf-ospf-segment-routing-extensions-24.txt for MPLS dataplane.
@deffn {OSPF Command} {segment-routing on} {}
@deffnx {OSPF Command} {no segment-routing} {}
@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
+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} {segment-routing prefix A.B.C.D/M index (0-65535) no-php-flag} {}
@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.
+that, only prefix with /32 corresponding to a loopback interface are
+currently supported. The 'no-php-flag' means NO Penultimate Hop Popping that
+allows SR node to request to its neighbor to not pop the label.
@end deffn
@deffn {Command} {show ip ospf database segment-routing} {}
write = 1;
}
+ /* debug ospf te */
+ if (IS_CONF_DEBUG_OSPF(te, TE) == OSPF_DEBUG_TE) {
+ vty_out(vty, "debug ospf%s te\n", str);
+ write = 1;
+ }
+
+ /* debug ospf sr */
+ if (IS_CONF_DEBUG_OSPF(sr, SR) == OSPF_DEBUG_SR) {
+ vty_out(vty, "debug ospf%s sr\n", str);
+ write = 1;
+ }
+
return write;
}
/* Macro for checking debug option. */
#define IS_DEBUG_OSPF_PACKET(a, b) (term_debug_ospf_packet[a] & OSPF_DEBUG_##b)
#define IS_DEBUG_OSPF(a, b) (term_debug_ospf_##a & OSPF_DEBUG_##b)
-#define IS_DEBUG_OSPF_EVENT IS_DEBUG_OSPF(event,EVENT)
+#define IS_DEBUG_OSPF_EVENT IS_DEBUG_OSPF(event, EVENT)
-#define IS_DEBUG_OSPF_NSSA IS_DEBUG_OSPF(nssa,NSSA)
+#define IS_DEBUG_OSPF_NSSA IS_DEBUG_OSPF(nssa, NSSA)
-#define IS_DEBUG_OSPF_TE IS_DEBUG_OSPF(te,TE)
+#define IS_DEBUG_OSPF_TE IS_DEBUG_OSPF(te, TE)
-#define IS_DEBUG_OSPF_EXT IS_DEBUG_OSPF(ext,EXT)
+#define IS_DEBUG_OSPF_EXT IS_DEBUG_OSPF(ext, EXT)
-#define IS_DEBUG_OSPF_SR IS_DEBUG_OSPF(sr,SR)
+#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)
*
* Module name: Extended Prefix/Link Opaque LSA
*
- * Author: Anselme Sawadogo <anselmesawadogo@gmail.com>
* 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.
+ * Copyright (C) 2016 - 2018 Orange Labs http://www.orange.com
*
- * 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.
+ * This program 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 of the License, 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.
+ * This program 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.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
*/
static struct ospf_ext_lp OspfEXT;
-/*------------------------------------------------------------------------------*
- * Followings are initialize/terminate functions for Extended Prefix/Link Opaque
- * LSA handling.
- *------------------------------------------------------------------------------*/
+/*
+ * -----------------------------------------------------------------------
+ * Followings are initialize/terminate functions for Extended Prefix/Link
+ * Opaque LSA handling.
+ * -----------------------------------------------------------------------
+ */
/* Extended Prefix Opaque LSA related callback functions */
-static int ospf_ext_pref_del_if(struct interface *ifp);
+static void ospf_ext_pref_ism_change(struct ospf_interface *oi, int old_status);
static void ospf_ext_pref_show_info(struct vty *vty, struct ospf_lsa *lsa);
static int ospf_ext_pref_lsa_originate(void *arg);
static struct ospf_lsa *ospf_ext_pref_lsa_refresh(struct ospf_lsa *lsa);
OspfEXT.iflist = list_new();
OspfEXT.iflist->del = del_ext_info;
- zlog_info("EXT: Register Extended Link Opaque LSA");
+ zlog_info("EXT (%s): Register Extended Link Opaque LSA", __func__);
rc = ospf_register_opaque_functab(
OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_EXTENDED_LINK_LSA,
- ospf_ext_link_new_if, /* new if */
- ospf_ext_link_del_if, /* del if */
+ ospf_ext_link_new_if, /* new if */
+ ospf_ext_link_del_if, /* del if */
ospf_ext_link_ism_change, /* ism change */
ospf_ext_link_nsm_change, /* nsm change */
NULL, /* Write router config. */
NULL); /* del_lsa_hook */
if (rc != 0) {
- zlog_warn("EXT: Failed to register Extended Link LSA");
+ zlog_warn("EXT (%s): Failed to register Extended Link LSA",
+ __func__);
return rc;
}
- zlog_info("EXT: Register Extended Prefix Opaque LSA");
+ zlog_info("EXT (%s): Register Extended Prefix Opaque LSA", __func__);
rc = ospf_register_opaque_functab(
OspfEXT.scope, OPAQUE_TYPE_EXTENDED_PREFIX_LSA,
- NULL, /* new interface */
- ospf_ext_pref_del_if, /* del interface */
- NULL, /* ism change */
+ NULL, /* new if handle by link */
+ NULL, /* del if handle by link */
+ ospf_ext_pref_ism_change, /* ism change */
NULL, /* nsm change */
ospf_sr_config_write_router, /* Write router config. */
NULL, /* Write interface conf. */
ospf_ext_pref_lsa_update, /* new_lsa_hook */
NULL); /* del_lsa_hook */
if (rc != 0) {
- zlog_warn("EXT: Failed to register Extended Prefix LSA");
+ zlog_warn("EXT (%s): Failed to register Extended Prefix LSA",
+ __func__);
return rc;
}
/*
* Extended Link/Prefix termination function
*
- * @paam - node
+ * @param - node
*
* @return - none
*/
void ospf_ext_term(void)
{
- if ((OspfEXT.scope != OSPF_OPAQUE_AREA_LSA)
- || (OspfEXT.scope != OSPF_OPAQUE_AS_LSA))
- zlog_warn(
- "EXT: Unable to unregister Extended Prefix "
- "Opaque LSA functions: Wrong scope!");
- else
- ospf_delete_opaque_functab(OspfEXT.scope,
- OPAQUE_TYPE_EXTENDED_PREFIX_LSA);
-
- ospf_delete_opaque_functab(OSPF_OPAQUE_AREA_LSA,
- OPAQUE_TYPE_EXTENDED_LINK_LSA);
-
list_delete_and_null(&OspfEXT.iflist);
OspfEXT.scope = 0;
OspfEXT.enabled = false;
- return;
}
-/*------------------------------------------------------------------------*
+/*
+ * ---------------------------------------------------------------------
* Followings are control functions for Extended Prefix/Link Opaque LSA
* parameters management.
- *------------------------------------------------------------------------*/
+ * ---------------------------------------------------------------------
+ */
+
/* Functions to free memory space */
static void del_ext_info(void *val)
{
XFREE(MTYPE_OSPF_EXT_PARAMS, val);
- return;
}
/* Increment instance value for Extended Prefix Opaque LSAs Opaque ID field */
if (exti->instance == key)
return exti;
- zlog_warn("lookup_linkparams_by_instance: Entry not found: key(%x)",
- key);
return NULL;
}
-/*------------------------------------------------------------------------*
+/*
+ * ----------------------------------------------------------------------
* The underlying subsection defines setters and unsetters to create and
* delete tlvs and subtlvs
- *------------------------------------------------------------------------*/
+ * ----------------------------------------------------------------------
+ */
/* Extended Prefix TLV - RFC7684 section 2.1 */
static void set_ext_prefix(struct ext_itf *exti, uint8_t route_type,
/* Prefix SID SubTLV - section 5 */
static void set_prefix_sid(struct ext_itf *exti, uint8_t algorithm,
- uint32_t value, int value_type)
+ uint32_t value, int value_type, uint8_t flags)
{
- uint8_t flags;
-
if ((algorithm != SR_ALGORITHM_SPF)
&& (algorithm != SR_ALGORITHM_STRICT_SPF)) {
zlog_warn(
- "OSPF_SR: unrecognized "
- "algorithm, not spf or strict spf");
+ "EXT (%s): unrecognized algorithm, not SPF or S-SPF",
+ __func__);
return;
}
- /* Set the flags according to the type of value field: label or index
- * other flags flags are cleared, in particular the No-PHP as the
- * Linux Kernel only supports Penultimate Hop Popping (PHP)
- */
+ /* Update flags according to the type of value field: label or index */
if (value_type == SID_LABEL)
- flags = EXT_SUBTLV_PREFIX_SID_VFLG;
- else
- flags = 0;
+ SET_FLAG(flags, EXT_SUBTLV_PREFIX_SID_VFLG);
/* set prefix sid subtlv for an extended prefix tlv */
TLV_TYPE(exti->node_sid) = htons(EXT_SUBTLV_PREFIX_SID);
exti->node_sid.value = htonl(value);
}
- return;
}
/* Adjacency SID SubTLV - section 6.1 */
exti->adj_sid[index].flags = flags; /* Set computed flags */
exti->adj_sid[index].mtid = 0; /* Multi-Topology is not supported */
exti->adj_sid[index].weight = 0; /* Load-Balancing is not supported */
- return;
+
}
/* LAN Adjacency SID SubTLV - section 6.2 */
exti->lan_sid[index].mtid = 0; /* Multi-Topology is not supported */
exti->lan_sid[index].weight = 0; /* Load-Balancing is not supported */
exti->lan_sid[index].neighbor_id = neighbor_id;
- return;
+
}
/* Experimental SubTLV from Cisco */
TLV_TYPE(exti->rmt_itf_addr) = htons(EXT_SUBTLV_RMT_ITF_ADDR);
TLV_LEN(exti->rmt_itf_addr) = htons(sizeof(struct in_addr));
exti->rmt_itf_addr.value = rmtif;
- return;
+
}
/*
* @return instance number if update is OK, 0 otherwise
*/
int ospf_ext_schedule_prefix_index(struct interface *ifp, uint32_t index,
- struct prefix_ipv4 *p)
+ struct prefix_ipv4 *p, uint8_t flags)
{
int rc = 0;
struct ext_itf *exti;
if (p != NULL) {
if (IS_DEBUG_OSPF_SR)
zlog_debug(
- "EXT (ospf_ext_schedule_prefix_index) "
- "Schedule new prefix %s/%d with index %d "
- "on interface %s",
- inet_ntoa(p->prefix), p->prefixlen, index,
- ifp->name);
+ "EXT (%s): Schedule new prefix %s/%u with "
+ "index %u on interface %s",
+ __func__, inet_ntoa(p->prefix), p->prefixlen,
+ index, ifp->name);
/* Set first Extended Prefix then the Prefix SID information */
set_ext_prefix(exti, OSPF_PATH_INTRA_AREA, EXT_TLV_PREF_NFLG,
*p);
- set_prefix_sid(exti, SR_ALGORITHM_SPF, index, SID_INDEX);
+ set_prefix_sid(exti, SR_ALGORITHM_SPF, index, SID_INDEX, flags);
/* Try to Schedule LSA */
SET_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE);
} else {
if (IS_DEBUG_OSPF_SR)
zlog_debug(
- "EXT (ospf_ext_schedule_prefix_index) "
- "Remove prefix for interface %s",
- ifp->name);
+ "EXT (%s): Remove prefix for interface %s",
+ __func__, ifp->name);
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED)) {
ospf_ext_pref_lsa_schedule(exti, FLUSH_THIS_LSA);
if (IS_DEBUG_OSPF_SR)
zlog_debug(
- "EXT (ospf_ext_update_sr): %s Extended LSAs for "
- "Segment Routing",
- enable ? "Enable" : "Disable");
+ "EXT (%s): %s Extended LSAs for Segment Routing ",
+ __func__, enable ? "Enable" : "Disable");
if (enable) {
OspfEXT.enabled = true;
OspfEXT.enabled = false;
}
}
-/*------------------------------------------------------------------------*
- * Followings are callback functions against generic Opaque-LSAs handling.
- *------------------------------------------------------------------------*/
+/*
+ * -----------------------------------------------------------------------
+ * Followings are callback functions against generic Opaque-LSAs handling
+ * -----------------------------------------------------------------------
+ */
/* Add new Interface in Extended Interface List */
static int ospf_ext_link_new_if(struct interface *ifp)
if (lookup_ext_by_ifp(ifp) != NULL) {
zlog_warn(
- "EXT (ospf_ext_link_new_if) interface %s"
- " is already in use",
- ifp ? ifp->name : "-");
+ "EXT (%s): interface %s is already in use",
+ __func__, ifp ? ifp->name : "-");
rc = 0; /* Do nothing here. */
return rc;
}
new = XCALLOC(MTYPE_OSPF_EXT_PARAMS, sizeof(struct ext_itf));
if (new == NULL) {
- zlog_warn("EXT: XCALLOC: %s", safe_strerror(errno));
+ zlog_warn("EXT (%s): XCALLOC: %s", __func__,
+ safe_strerror(errno));
return rc;
}
struct ext_itf *exti;
int rc = -1;
- if ((exti = lookup_ext_by_ifp(ifp)) != NULL) {
+ exti = lookup_ext_by_ifp(ifp);
+ if (exti != NULL) {
struct list *iflist = OspfEXT.iflist;
- /* Skip Extended Prefix interface */
- if (exti->stype == PREF_SID)
- return 0;
-
/* Dequeue listnode entry from the list. */
listnode_delete(iflist, exti);
- /* Avoid misjudgement in the next lookup. */
- if (listcount(iflist) == 0)
- iflist->head = iflist->tail = NULL;
-
XFREE(MTYPE_OSPF_EXT_PARAMS, exti);
rc = 0;
} else {
zlog_warn(
- "EXT (ospf_ext_link_del_if) interface %s "
- "is not found",
- ifp ? ifp->name : "-");
+ "EXT (%s): interface %s is not found",
+ __func__, ifp ? ifp->name : "-");
}
return rc;
}
-/* Remove existing Interface from Extended Interface List */
-static int ospf_ext_pref_del_if(struct interface *ifp)
+/*
+ * Determine if an Interface belongs to an Extended Link Adjacency or LAN Adj.
+ * type and allocate new instance value accordingly
+ */
+static void ospf_ext_link_ism_change(struct ospf_interface *oi, int old_status)
{
struct ext_itf *exti;
- int rc = -1;
-
- if ((exti = lookup_ext_by_ifp(ifp)) != NULL) {
- struct list *iflist = OspfEXT.iflist;
- /* Look only to Extended Prefix interface */
- if (exti->stype != PREF_SID)
- return 0;
-
- /* Dequeue listnode entry from the list. */
- listnode_delete(iflist, exti);
+ /* Get interface information for Segment Routing */
+ exti = lookup_ext_by_ifp(oi->ifp);
+ if (exti == NULL) {
+ zlog_warn(
+ "EXT (%s): Cannot get Extended info. from OI(%s)",
+ __func__, IF_NAME(oi));
+ return;
+ }
- /* Avoid misjudgement in the next lookup. */
- if (listcount(iflist) == 0)
- iflist->head = iflist->tail = NULL;
+ /* Determine if interface is related to Adjacency or LAN Adj. SID */
+ if (oi->type != OSPF_IFTYPE_LOOPBACK) {
+ if (oi->state == ISM_DR)
+ exti->stype = LAN_ADJ_SID;
+ else
+ exti->stype = ADJ_SID;
- XFREE(MTYPE_OSPF_EXT_PARAMS, exti);
+ exti->instance = get_ext_link_instance_value();
- rc = 0;
- } else {
- zlog_warn(
- "EXT (ospf_ext_pref_del_if) interface %s "
- "is not found",
- ifp ? ifp->name : "-");
+ zlog_debug(
+ "EXT (%s): Set %s SID to interface %s ", __func__,
+ exti->stype == ADJ_SID ? "Adj." : "LAN Adj.",
+ oi->ifp->name);
}
-
- return rc;
}
/*
- * Determine if an Extended Interface is Link or Prefix type and
+ * Determine if an Interface belongs to an Extended Prefix and
* allocate new instance value accordingly
*/
-static void ospf_ext_link_ism_change(struct ospf_interface *oi, int old_status)
+static void ospf_ext_pref_ism_change(struct ospf_interface *oi, int old_status)
{
struct ext_itf *exti;
/* Get interface information for Segment Routing */
- if ((exti = lookup_ext_by_ifp(oi->ifp)) == NULL) {
+ exti = lookup_ext_by_ifp(oi->ifp);
+ if (exti == NULL) {
zlog_warn(
- "EXT (ospf_ext_link_ism_change) Cannot get Extended "
- "information from OI(%s)",
- IF_NAME(oi));
+ "EXT (%s): Cannot get Extended info. from OI(%s)",
+ __func__, IF_NAME(oi));
return;
}
- /* Determine if interface is related to Node SID or Adjacency/LAN SID */
+ /* Determine if interface is related to a Node SID */
if (oi->type == OSPF_IFTYPE_LOOPBACK) {
exti->stype = PREF_SID;
exti->instance = get_ext_pref_instance_value();
- } else {
- exti->stype = ADJ_SID;
- exti->instance = get_ext_link_instance_value();
+
+ zlog_debug(
+ "EXT (%s): Set Node SID to interface %s ", __func__,
+ oi->ifp->name);
+
+ /* Complete SRDB if the interface belongs to a Prefix */
+ ospf_sr_update_prefix(oi->ifp, oi->address);
}
- zlog_debug("EXT (ospf_ext_link_ism_change) Set %s SID to interface %s ",
- exti->stype == PREF_SID ? "Node" : "Adj.", oi->ifp->name);
}
/*
return;
/* Get interface information for Segment Routing */
- if ((exti = lookup_ext_by_ifp(oi->ifp)) == NULL) {
+ exti = lookup_ext_by_ifp(oi->ifp);
+ if (exti == NULL) {
zlog_warn(
- "EXT (ospf_ext_link_nsm_change) Cannot get Extended "
- "information from OI(%s)",
- IF_NAME(oi));
+ "EXT (%s): Cannot get Extended info. from OI(%s)",
+ __func__, IF_NAME(oi));
return;
}
if (oi->area == NULL || oi->area->ospf == NULL) {
zlog_warn(
- "EXT (ospf_ext_link_nsm_change) Cannot refer to "
- "OSPF from OI(%s)",
- IF_NAME(oi));
+ "EXT (%s): Cannot refer to OSPF from OI(%s)",
+ __func__, IF_NAME(oi));
return;
}
return;
}
+ if (IS_DEBUG_OSPF_SR)
+ zlog_debug(
+ "EXT (%s): Complete %s SID to interface %s ", __func__,
+ exti->stype == ADJ_SID ? "Adj." : "LAN Adj.",
+ oi->ifp->name);
+
/* flood this links params if everything is ok */
SET_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE);
if (OspfEXT.enabled) {
ospf_ext_link_lsa_schedule(exti, REORIGINATE_THIS_LSA);
}
- return;
}
/* Callbacks to handle Extended Link Segment Routing LSA information */
{
/* Sanity Check */
if (lsa == NULL) {
- zlog_warn(
- "EXT (ospf_ext_link_lsa_update): Abort! LSA is "
- "NULL");
+ zlog_warn("EXT (%s): Abort! LSA is NULL", __func__);
return -1;
}
/* Sanity Check */
if (lsa == NULL) {
- zlog_warn(
- "EXT (ospf_ext_pref_lsa_update): Abort! LSA is "
- "NULL");
+ zlog_warn("EXT (%s): Abort! LSA is NULL", __func__);
return -1;
}
+ /* Check if it is not my LSA */
+ if (IS_LSA_SELF(lsa))
+ return 0;
+
/* Process only Extended Prefix LSA */
if (GET_OPAQUE_TYPE(ntohl(lsa->data->id.s_addr))
!= OPAQUE_TYPE_EXTENDED_PREFIX_LSA)
return 0;
}
-/*------------------------------------------------------------------------*
+/*
+ * -------------------------------------------------------
* Followings are OSPF protocol processing functions for
* Extended Prefix/Link Opaque LSA
- *------------------------------------------------------------------------*/
+ * -------------------------------------------------------
+ */
static void build_tlv_header(struct stream *s, struct tlv_header *tlvh)
{
stream_put(s, tlvh, sizeof(struct tlv_header));
- return;
+
}
static void build_tlv(struct stream *s, struct tlv_header *tlvh)
build_tlv_header(s, tlvh);
stream_put(s, TLV_DATA(tlvh), TLV_BODY_SIZE(tlvh));
}
- return;
+
}
/* Build an Extended Prefix Opaque LSA body for extended prefix TLV */
/* Adjust Extended Prefix TLV size */
TLV_LEN(exti->prefix) =
- htons(ntohs(TLV_LEN(exti->node_sid)) + EXT_TLV_PREFIX_SIZE);
+ htons(ntohs(TLV_LEN(exti->node_sid)) + EXT_TLV_PREFIX_SIZE
+ + TLV_HDR_SIZE);
/* Build LSA body for an Extended Prefix TLV */
build_tlv_header(s, &exti->prefix.header);
/* Then add Prefix SID SubTLV */
build_tlv(s, &exti->node_sid.header);
- return;
}
/* Build an Extended Link Opaque LSA body for extended link TLV */
static void ospf_ext_link_lsa_body_set(struct stream *s, struct ext_itf *exti)
{
+ size_t size;
/* Sanity check */
if ((exti == NULL)
if (exti->stype == ADJ_SID) {
/* Adjust Extended Link TLV size for Adj. SID */
- TLV_LEN(exti->link) =
- htons(EXT_TLV_LINK_SIZE + 2 * EXT_SUBTLV_ADJ_SID_SIZE
- + 2 * TLV_HDR_SIZE + EXT_SUBTLV_RMT_ITF_ADDR_SIZE
- + TLV_HDR_SIZE);
+ size = EXT_TLV_LINK_SIZE + 2 * EXT_SUBTLV_ADJ_SID_SIZE
+ + 2 * TLV_HDR_SIZE;
+ if (ntohs(TLV_TYPE(exti->rmt_itf_addr)) != 0)
+ size = size + EXT_SUBTLV_RMT_ITF_ADDR_SIZE
+ + TLV_HDR_SIZE;
+ zlog_debug("EXT (%s): TLV size = %u", __func__, size);
+ TLV_LEN(exti->link) = htons(size);
/* Build LSA body for an Extended Link TLV with Adj. SID */
build_tlv_header(s, &exti->link.header);
/* then add Ajacency SubTLVs */
build_tlv(s, &exti->adj_sid[1].header);
build_tlv(s, &exti->adj_sid[0].header);
- /* Cisco experimental SubTLV */
- build_tlv(s, &exti->rmt_itf_addr.header);
+
+ /* Add Cisco experimental SubTLV if interface is PtoP */
+ if (ntohs(TLV_TYPE(exti->rmt_itf_addr)) != 0)
+ build_tlv(s, &exti->rmt_itf_addr.header);
} else {
/* Adjust Extended Link TLV size for LAN SID */
- TLV_LEN(exti->link) = htons(EXT_TLV_LINK_SIZE
- + 2 * EXT_SUBTLV_LAN_ADJ_SID_SIZE
- + 2 * TLV_HDR_SIZE);
+ size = EXT_TLV_LINK_SIZE
+ + 2 * (EXT_SUBTLV_LAN_ADJ_SID_SIZE + TLV_HDR_SIZE);
+ TLV_LEN(exti->link) = htons(size);
/* Build LSA body for an Extended Link TLV with LAN SID */
build_tlv_header(s, &exti->link.header);
build_tlv(s, &exti->lan_sid[0].header);
}
- return;
}
/* Create new Extended Prefix opaque-LSA for every extended prefix */
struct stream *s;
struct lsa_header *lsah;
struct ospf_lsa *new = NULL;
+ struct ospf *top;
u_char options, lsa_type;
struct in_addr lsa_id;
struct in_addr router_id;
return NULL;
/* Create a stream for LSA. */
- if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) {
- zlog_warn("EXT: stream_new() error");
+ s = stream_new(OSPF_MAX_LSA_SIZE);
+ if (s == NULL) {
+ zlog_warn("EXT (%s): stream_new() error", __func__);
return NULL;
}
lsa_type = OspfEXT.scope;
- /* LSA ID is a variable number identifying different instances of
- * Extended Prefix Opaque LSA from the same router see RFC 7684 */
+ /*
+ * LSA ID is a variable number identifying different instances of
+ * Extended Prefix Opaque LSA from the same router see RFC 7684
+ */
tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_EXTENDED_PREFIX_LSA, exti->instance);
lsa_id.s_addr = htonl(tmp);
/* Fix Options and Router ID depending of the flooding scope */
if ((OspfEXT.scope == OSPF_OPAQUE_AS_LSA) || (area == NULL)) {
options = OSPF_OPTION_E;
- struct ospf *top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- router_id = top->router_id;
+ top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
+ router_id.s_addr = top ? top->router_id.s_addr : 0;
} else {
options |= LSA_OPTIONS_GET(area); /* Get area default option */
options |= LSA_OPTIONS_NSSA_GET(area);
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug(
- "EXT: LSA[Type%d:%s]: Create an Opaque-LSA/Extended "
- "Prefix Opaque LSA instance",
- lsa_type, inet_ntoa(lsa_id));
+ "EXT (%s): LSA[Type%u:%s]: Create an Opaque-LSA "
+ "Extended Prefix Opaque LSA instance",
+ __func__, lsa_type, inet_ntoa(lsa_id));
/* Set opaque-LSA body fields. */
lsah->length = htons(length);
/* Now, create an OSPF LSA instance. */
- if ((new = ospf_lsa_new()) == NULL) {
- zlog_warn("EXT: ospf_lsa_new() error");
+ new = ospf_lsa_new();
+ if (new == NULL) {
+ zlog_warn("EXT (%s): ospf_lsa_new() error", __func__);
stream_free(s);
return NULL;
}
- if ((new->data = ospf_lsa_data_new(length)) == NULL) {
- zlog_warn("EXT: ospf_lsa_data_new() error");
+ new->data = ospf_lsa_data_new(length);
+ if (new->data == NULL) {
+ zlog_warn("EXT (%s): ospf_lsa_data_new() error", __func__);
ospf_lsa_unlock(&new);
new = NULL;
stream_free(s);
return NULL;
}
+ /* Segment Routing belongs only to default VRF */
+ new->vrf_id = VRF_DEFAULT;
new->area = area;
SET_FLAG(new->flags, OSPF_LSA_SELF);
memcpy(new->data, lsah, length);
return NULL;
/* Create a stream for LSA. */
- if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) {
- zlog_warn("EXT: stream_new() error");
+ s = stream_new(OSPF_MAX_LSA_SIZE);
+ if (s == NULL) {
+ zlog_warn("EXT (%s): stream_new() error", __func__);
return NULL;
}
lsah = (struct lsa_header *)STREAM_DATA(s);
/* Extended Link Opaque LSA are only flooded within an area */
lsa_type = OSPF_OPAQUE_AREA_LSA;
- /* LSA ID is a variable number identifying different instances of
- * Extended Link Opaque LSA from the same router see RFC 7684 */
+ /*
+ * LSA ID is a variable number identifying different instances of
+ * Extended Link Opaque LSA from the same router see RFC 7684
+ */
tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_EXTENDED_LINK_LSA, exti->instance);
lsa_id.s_addr = htonl(tmp);
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
zlog_debug(
- "EXT: LSA[Type%d:%s]: Create an Opaque-LSA/Extended "
- "Link Opaque LSA instance",
- lsa_type, inet_ntoa(lsa_id));
+ "EXT (%s) LSA[Type%u:%s]: Create an Opaque-LSA "
+ "Extended Link Opaque LSA instance",
+ __func__, lsa_type, inet_ntoa(lsa_id));
/* Set opaque-LSA header fields. */
lsa_header_set(s, options, lsa_type, lsa_id, area->ospf->router_id);
lsah->length = htons(length);
/* Now, create an OSPF LSA instance. */
- if ((new = ospf_lsa_new()) == NULL) {
- zlog_warn("EXT: ospf_lsa_new() error");
+ new = ospf_lsa_new();
+ if (new == NULL) {
+ zlog_warn("EXT (%s): ospf_lsa_new() error", __func__);
stream_free(s);
return NULL;
}
- if ((new->data = ospf_lsa_data_new(length)) == NULL) {
- zlog_warn("EXT: ospf_lsa_data_new() error");
+ new->data = ospf_lsa_data_new(length);
+ if (new->data == NULL) {
+ zlog_warn("EXT (%s): ospf_lsa_data_new() error", __func__);
ospf_lsa_unlock(&new);
new = NULL;
stream_free(s);
return NULL;
}
+ /* Segment Routing belongs only to default VRF */
+ new->vrf_id = VRF_DEFAULT;
new->area = area;
SET_FLAG(new->flags, OSPF_LSA_SELF);
memcpy(new->data, lsah, length);
return new;
}
-/* Process the origination of an Extended Prefix Opaque LSA
- * for every extended prefix TLV */
+/*
+ * Process the origination of an Extended Prefix Opaque LSA
+ * for every extended prefix TLV
+ */
static int ospf_ext_pref_lsa_originate1(struct ospf_area *area,
struct ext_itf *exti)
{
/* Create new Opaque-LSA/Extended Prefix Opaque LSA instance. */
- if ((new = ospf_ext_pref_lsa_new(area, exti)) == NULL) {
- zlog_warn("EXT: ospf_ext_pref_lsa_new() error");
+ new = ospf_ext_pref_lsa_new(area, exti);
+ if (new == NULL) {
+ zlog_warn("EXT (%s): ospf_ext_pref_lsa_new() error", __func__);
return rc;
}
/* Install this LSA into LSDB. */
if (ospf_lsa_install(area->ospf, NULL /*oi */, new) == NULL) {
- zlog_warn("EXT: ospf_lsa_install() error");
+ zlog_warn("EXT (%s): ospf_lsa_install() error", __func__);
ospf_lsa_unlock(&new);
return rc;
}
/* Now this Extended Prefix Opaque LSA info parameter entry has
- * associated LSA. */
+ * associated LSA.
+ */
SET_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED);
/* Update new LSA origination count. */
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
char area_id[INET_ADDRSTRLEN];
+
strncpy(area_id, inet_ntoa(area->area_id), INET_ADDRSTRLEN);
zlog_debug(
- "EXT: LSA[Type%d:%s]: Originate Opaque-LSA/Extended "
- "Prefix Opaque LSA: Area(%s), Link(%s)",
- new->data->type, inet_ntoa(new->data->id), area_id,
- exti->ifp->name);
+ "EXT (%s): LSA[Type%u:%s]: Originate Opaque-LSA "
+ "Extended Prefix Opaque LSA: Area(%s), Link(%s)",
+ __func__, new->data->type, inet_ntoa(new->data->id),
+ area_id, exti->ifp->name);
ospf_lsa_header_dump(new->data);
}
return rc;
}
-/* Process the origination of an Extended Link Opaque LSA
- * for every extended link TLV */
+/*
+ * Process the origination of an Extended Link Opaque LSA
+ * for every extended link TLV
+ */
static int ospf_ext_link_lsa_originate1(struct ospf_area *area,
struct ext_itf *exti)
{
int rc = -1;
/* Create new Opaque-LSA/Extended Link Opaque LSA instance. */
- if ((new = ospf_ext_link_lsa_new(area, exti)) == NULL) {
- zlog_warn("EXT: ospf_ext_link_lsa_new() error");
+ new = ospf_ext_link_lsa_new(area, exti);
+ if (new == NULL) {
+ zlog_warn("EXT (%s): ospf_ext_link_lsa_new() error", __func__);
return rc;
}
/* Install this LSA into LSDB. */
if (ospf_lsa_install(area->ospf, NULL /*oi */, new) == NULL) {
- zlog_warn("EXT: ospf_lsa_install() error");
+ zlog_warn("EXT (%s): ospf_lsa_install() error", __func__);
ospf_lsa_unlock(&new);
return rc;
}
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
char area_id[INET_ADDRSTRLEN];
+
strncpy(area_id, inet_ntoa(area->area_id), INET_ADDRSTRLEN);
zlog_debug(
- "EXT: LSA[Type%d:%s]: Originate Opaque-LSA/Extended "
- "Link Opaque LSA: Area(%s), Link(%s)",
- new->data->type, inet_ntoa(new->data->id), area_id,
- exti->ifp->name);
+ "EXT (%s): LSA[Type%u:%s]: Originate Opaque-LSA "
+ "Extended Link Opaque LSA: Area(%s), Link(%s)",
+ __func__, new->data->type, inet_ntoa(new->data->id),
+ area_id, exti->ifp->name);
ospf_lsa_header_dump(new->data);
}
if (!OspfEXT.enabled) {
zlog_info(
- "EXT: Segment Routing "
- "functionality is Disabled now.");
+ "EXT (%s): Segment Routing "
+ "functionality is Disabled now", __func__);
rc = 0; /* This is not an error case. */
return rc;
}
if (IS_DEBUG_OSPF_SR)
zlog_debug(
- "EXT (ospf_ext_pref_lsa_originate) "
- "Start Originate Prefix LSA for area %s",
- inet_ntoa(area->area_id));
+ "EXT (%s): Start Originate Prefix LSA for area %s",
+ __func__, inet_ntoa(area->area_id));
/* Check if Extended Prefix Opaque LSA is already engaged */
for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti)) {
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED)) {
if (CHECK_FLAG(exti->flags,
EXT_LPFLG_LSA_FORCED_REFRESH)) {
- zlog_warn("EXT: Refresh instead of Originate");
+ zlog_warn(
+ "EXT (%s): Refresh instead of "
+ "Originate", __func__);
UNSET_FLAG(exti->flags,
EXT_LPFLG_LSA_FORCED_REFRESH);
ospf_ext_pref_lsa_schedule(exti,
/* Ok, let's try to originate an LSA */
if (IS_DEBUG_OSPF_SR)
zlog_debug(
- "EXT: Let's finally reoriginate the "
- "LSA 7.0.0.%d for Itf %s",
- exti->instance,
+ "EXT (%s): Let's finally reoriginate the "
+ "LSA 7.0.0.%u for Itf %s",
+ __func__, exti->instance,
exti->ifp ? exti->ifp->name : "");
ospf_ext_pref_lsa_originate1(area, exti);
}
if (!OspfEXT.enabled) {
zlog_info(
- "EXT: Segment Routing "
- "functionality is Disabled now.");
+ "EXT (%s): Segment Routing "
+ "functionality is Disabled now", __func__);
rc = 0; /* This is not an error case. */
return rc;
}
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED)) {
if (CHECK_FLAG(exti->flags,
EXT_LPFLG_LSA_FORCED_REFRESH)) {
- zlog_warn("EXT: Refresh instead of Originate");
+ zlog_warn(
+ "EXT (%s): Refresh instead of "
+ "Originate", __func__);
UNSET_FLAG(exti->flags,
EXT_LPFLG_LSA_FORCED_REFRESH);
ospf_ext_link_lsa_schedule(exti,
/* Ok, let's try to originate an LSA */
if (IS_DEBUG_OSPF_SR)
zlog_debug(
- "EXT Let's finally reoriginate the "
- "LSA 8.0.0.%d for Itf %s through the Area %s",
- exti->instance,
+ "EXT (%s): Let's finally reoriginate the "
+ "LSA 8.0.0.%u for Itf %s through the Area %s",
+ __func__, exti->instance,
exti->ifp ? exti->ifp->name : "-",
inet_ntoa(area->area_id));
ospf_ext_link_lsa_originate1(area, exti);
* Opaque LSA status change.
* It seems a slip among routers in the routing domain.
*/
- zlog_info("EXT: Segment Routing functionality is Disabled");
+ zlog_info(
+ "EXT (%s): Segment Routing functionality is "
+ "Disabled", __func__);
/* Flush it anyway. */
lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
}
/* Lookup this lsa corresponding Extended parameters */
- if ((exti = lookup_ext_by_instance(lsa)) == NULL) {
- zlog_warn("EXT: Invalid parameter LSA ID");
+ exti = lookup_ext_by_instance(lsa);
+ if (exti == NULL) {
+ zlog_warn("EXT (%s): Invalid parameter LSA ID", __func__);
/* Flush it anyway. */
lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
}
/* Check if Interface was not disable in the interval */
if ((exti != NULL) && !CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE)) {
- zlog_warn("EXT: Interface was Disabled: Flush it!");
+ zlog_warn("EXT (%s): Interface was Disabled: Flush it!",
+ __func__);
/* Flush it anyway. */
lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
}
new = ospf_ext_pref_lsa_new(area, exti);
if (new == NULL) {
- zlog_warn("EXT: ospf_ext_pref_lsa_new() error");
+ zlog_warn("EXT (%s): ospf_ext_pref_lsa_new() error", __func__);
return NULL;
}
new->data->ls_seqnum = lsa_seqnum_increment(lsa);
- /* Install this LSA into LSDB. */
- /* Given "lsa" will be freed in the next function. */
- /* As area could be NULL i.e. when using OPAQUE_LSA_AS, we prefer to use
- * ospf_lookup() to get ospf instance */
+ /*
+ * Install this LSA into LSDB
+ * Given "lsa" will be freed in the next function
+ * As area could be NULL i.e. when using OPAQUE_LSA_AS, we prefer to use
+ * ospf_lookup() to get ospf instance
+ */
if (area)
top = area->ospf;
else
top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
- zlog_warn("EXT: ospf_lsa_install() error");
+ zlog_warn("EXT (%s): ospf_lsa_install() error", __func__);
ospf_lsa_unlock(&new);
return NULL;
}
/* Debug logging. */
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
- zlog_debug("EXT: LSA[Type%d:%s]: Refresh Extended Prefix LSA",
- new->data->type, inet_ntoa(new->data->id));
+ zlog_debug(
+ "EXT (%s): LSA[Type%u:%s] Refresh Extended Prefix LSA",
+ __func__, new->data->type, inet_ntoa(new->data->id));
ospf_lsa_header_dump(new->data);
}
* change. It seems a slip among routers in the routing domain.
*/
zlog_info(
- "EXT (ospf_ext_link_lsa_refresh): Segment Routing "
- "functionality is Disabled");
+ "EXT (%s): Segment Routing functionality is Disabled",
+ __func__);
/* Flush it anyway. */
lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
}
- /* Lookup this lsa corresponding Extended parameters */
- if ((exti = lookup_ext_by_instance(lsa)) == NULL) {
- zlog_warn(
- "EXT (ospf_ext_link_lsa_refresh): Invalid parameter "
- "LSA ID");
+ /* Lookup this LSA corresponding Extended parameters */
+ exti = lookup_ext_by_instance(lsa);
+ if (exti == NULL) {
+ zlog_warn("EXT (%s): Invalid parameter LSA ID", __func__);
/* Flush it anyway. */
lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
}
/* Check if Interface was not disable in the interval */
if ((exti != NULL) && !CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE)) {
zlog_warn(
- "EXT (ospf_ext_link_lsa_refresh): Interface was "
- "Disabled: Flush it!");
+ "EXT (%s): Interface was Disabled: Flush it!",
+ __func__);
lsa->data->ls_age = htons(OSPF_LSA_MAXAGE);
}
- /* If the lsa's age reached to MaxAge, start flushing procedure. */
+ /* If the lsa's age reached to MaxAge, start flushing procedure */
if (IS_LSA_MAXAGE(lsa)) {
if (exti)
UNSET_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED);
return NULL;
}
- /* Create new Opaque-LSA/MPLS-TE instance. */
- if ((new = ospf_ext_link_lsa_new(area, exti)) == NULL) {
- zlog_warn(
- "EXT (ospf_ext_link_lsa_refresh): Error creating "
- "new LSA");
+ /* Create new Opaque-LSA/Extended Link instance */
+ new = ospf_ext_link_lsa_new(area, exti);
+ if (new == NULL) {
+ zlog_warn("EXT (%s): Error creating new LSA", __func__);
return NULL;
}
new->data->ls_seqnum = lsa_seqnum_increment(lsa);
/* Install this LSA into LSDB. */
- /* Given "lsa" will be freed in the next function. */
+ /* Given "lsa" will be freed in the next function */
if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) {
- zlog_warn(
- "EXT (ospf_ext_link_lsa_refresh): Error installing "
- "new LSA");
+ zlog_warn("EXT (%s): Error installing new LSA", __func__);
ospf_lsa_unlock(&new);
return NULL;
}
/* Debug logging. */
if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
zlog_debug(
- "EXT (ospf_ext_link_lsa_refresh): LSA[Type%d:%s]: "
- "Refresh Extended Link LSA",
- new->data->type, inet_ntoa(new->data->id));
+ "EXT (%s): LSA[Type%u:%s]: Refresh Extended Link LSA",
+ __func__, new->data->type, inet_ntoa(new->data->id));
ospf_lsa_header_dump(new->data);
}
return;
zlog_debug(
- "EXT (ospf_ext_pref_lsa_schedule): Schedule %s%s%s LSA "
- "for interface %s",
+ "EXT (%s): Schedule %s%s%s LSA for interface %s", __func__,
opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
opcode == REFRESH_THIS_LSA ? "Refresh" : "",
opcode == FLUSH_THIS_LSA ? "Flush" : "",
/* Set LSA header information */
if (exti->area == NULL) {
zlog_warn(
- "EXT (ospf_ext_pref_lsa_schedule): Flooding is "
- "Area scope but area is not yet set");
+ "EXT (%s): Flooding is Area scope but area is not yet "
+ "set", __func__);
if (OspfEXT.area == NULL) {
top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
OspfEXT.area = ospf_area_lookup_by_area_id(
ospf_opaque_lsa_flush_schedule(&lsa);
break;
default:
- zlog_warn("EXT (ospf_ext_pref_lsa_schedule): Unknown opcode");
+ zlog_warn("EXT (%s): Unknown opcode", __func__);
break;
}
- return;
}
/* Schedule Extended Link Opaque LSA origination/refreshment/flushing */
return;
zlog_debug(
- "EXT (ospf_ext_link_lsa_schedule): Schedule %s%s%s LSA "
- "for interface %s",
+ "EXT (%s): Schedule %s%s%s LSA for interface %s", __func__,
opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
opcode == REFRESH_THIS_LSA ? "Refresh" : "",
opcode == FLUSH_THIS_LSA ? "Flush" : "",
/* Set LSA header information */
if (exti->area == NULL) {
zlog_warn(
- "EXT (ospf_ext_link_lsa_schedule): Flooding is "
- "Area scope but area is not yet set");
+ "EXT (%s): Flooding is Area scope but area is not "
+ "yet set", __func__);
if (OspfEXT.area == NULL) {
top = ospf_lookup_by_vrf_id(VRF_DEFAULT);
OspfEXT.area = ospf_area_lookup_by_area_id(
ospf_opaque_lsa_flush_schedule(&lsa);
break;
default:
- zlog_warn("EXT (ospf_ext_link_lsa_schedule): Unknown opcode");
+ zlog_warn("EXT (%s): Unknown opcode", __func__);
break;
}
- return;
}
/* Schedule Extended Link or Prefix depending of the Type of LSA */
ospf_ext_link_lsa_schedule(exti, op);
}
-/*------------------------------------------------------------------------*
+/*
+ * ------------------------------------
* Followings are vty show functions.
- *------------------------------------------------------------------------*/
+ * ------------------------------------
+ */
+
/* Cisco experimental SubTLV */
static uint16_t show_vty_ext_link_rmt_itf_addr(struct vty *vty,
struct tlv_header *tlvh)
{
struct ext_subtlv_rmt_itf_addr *top;
+
top = (struct ext_subtlv_rmt_itf_addr *)tlvh;
vty_out(vty,
- " Remote Interface Address Sub-TLV: Length %d\n "
+ " Remote Interface Address Sub-TLV: Length %u\n "
"Address: %s\n",
ntohs(top->header.length), inet_ntoa(top->value));
struct ext_subtlv_adj_sid *top = (struct ext_subtlv_adj_sid *)tlvh;
vty_out(vty,
- " Adj-SID Sub-TLV: Length %d\n\tFlags: "
- "0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\t%s: %d\n",
+ " Adj-SID Sub-TLV: Length %u\n\tFlags: "
+ "0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\t%s: %u\n",
ntohs(top->header.length), top->flags, top->mtid, top->weight,
CHECK_FLAG(top->flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG) ? "Label"
: "Index",
(struct ext_subtlv_lan_adj_sid *)tlvh;
vty_out(vty,
- " LAN-Adj-SID Sub-TLV: Length %d\n\tFlags: "
+ " LAN-Adj-SID Sub-TLV: Length %u\n\tFlags: "
"0x%x\n\tMT-ID:0x%x\n\tWeight: 0x%x\n\tNeighbor ID: "
- "%s\n\tLabel: %d\n",
+ "%s\n\tLabel: %u\n",
ntohs(top->header.length), top->flags, top->mtid, top->weight,
CHECK_FLAG(top->flags, EXT_SUBTLV_LINK_ADJ_SID_VFLG) ? "Label"
: "Index",
uint16_t sum = 0;
vty_out(vty,
- " Extended Link TLV: Length %d\n Link Type: 0x%x\n"
+ " Extended Link TLV: Length %u\n Link Type: 0x%x\n"
" Link ID: %s\n",
ntohs(top->header.length), top->link_type,
inet_ntoa(top->link_id));
}
}
- return;
}
/* Prefix SID SubTLV */
(struct ext_subtlv_prefix_sid *)tlvh;
vty_out(vty,
- " Prefix SID Sub-TLV: Length %d\n\tAlgorithm: "
- "%d\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\t%s: %d\n",
+ " Prefix SID Sub-TLV: Length %u\n\tAlgorithm: "
+ "%u\n\tFlags: 0x%x\n\tMT-ID:0x%x\n\t%s: %u\n",
ntohs(top->header.length), top->algorithm, top->flags,
top->mtid,
CHECK_FLAG(top->flags, EXT_SUBTLV_PREFIX_SID_VFLG) ? "Label"
uint16_t sum = 0;
vty_out(vty,
- " Extended Prefix TLV: Length %d\n\tRoute Type: %d\n"
- "\tAddress Family: 0x%x\n\tFlags: 0x%x\n\tAddress: %s/%d\n",
+ " Extended Prefix TLV: Length %u\n\tRoute Type: %u\n"
+ "\tAddress Family: 0x%x\n\tFlags: 0x%x\n\tAddress: %s/%u\n",
ntohs(top->header.length), top->route_type, top->af, top->flags,
inet_ntoa(top->address), top->pref_length);
}
}
- return;
}
*
* Module name: Extended Prefix/Link Opaque LSA header definition
*
- * Author: Anselme Sawadogo <anselmesawadogo@gmail.com>
* 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.
+ * Copyright (C) 2016 - 2018 Orange Labs http://www.orange.com
*
- * 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.
+ * This program 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 of the License, 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.
+ * This program 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.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _FRR_OSPF_EXT_PREF_H_
*
*
* Type: IANA has assigned '7' for Extended Prefix Opaque LSA
- * and '8' for Extended Link 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
*
/* Global use constant numbers */
-#define MAX_LEGAL_EXT_INSTANCE_NUM (0xffff)
+#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_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 */
+/*
+ * Extended Prefix and Extended Prefix Range TLVs'
+ * Address family flag for IPv4
+ */
#define EXT_TLV_PREF_AF_IPV4 0
/* Extended Prefix TLV Flags */
/* Flags to manage this Extended Prefix/Link Opaque LSA */
uint32_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 */
+ /*
+ * Scope is area Opaque Type 10 or AS Opaque LSA Type 11 for
+ * Extended Prefix and area Opaque Type 10 for Extended Link
+ */
uint8_t scope;
/* area pointer if flooding is Type 10 Null if flooding is AS scope */
/* 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 *, uint32_t,
- struct prefix_ipv4 *);
+extern void ospf_ext_update_sr(bool enable);
+extern int ospf_ext_schedule_prefix_index(struct interface *ifp,
+ uint32_t index,
+ struct prefix_ipv4 *p,
+ uint8_t flags);
#endif /* _FRR_OSPF_EXT_PREF_H_ */
if (ospf_router_info_init() != 0)
exit(1);
- /* Force Extended Prefix/Link to Type 10 */
if (ospf_ext_init() != 0)
exit(1);
struct ri_pce_subtlv_cap_flag pce_cap_flag;
};
-/* Store Router Information Segment Routing TLV and SubTLV in network byte order. */
+/*
+ * Store Router Information Segment Routing TLV and SubTLV
+ * in network byte order
+ */
struct ospf_ri_sr_info {
bool enabled;
/* Algorithms supported by the node */
return rc;
}
-static int ospf_router_info_unregister()
-{
-
- if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA)
- && (OspfRI.scope != OSPF_OPAQUE_AREA_LSA)) {
- zlog_warn(
- "Unable to unregister Router Info functions: Wrong scope!");
- return -1;
- }
-
- ospf_delete_opaque_functab(OspfRI.scope,
- OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
-
- OspfRI.registered = 0;
- return 0;
-}
-
void ospf_router_info_term(void)
{
OspfRI.enabled = false;
- ospf_router_info_unregister();
-
return;
}
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;
TLV_TYPE(OspfRI.sr_info.algo) = htons(RI_SR_TLV_SR_ALGORITHM);
TLV_LEN(OspfRI.sr_info.algo) = htons(sizeof(uint8_t));
- return;
}
/* unset Aglogithm SubTLV */
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 */
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()
+static void unset_sr_sid_label_range(void)
{
TLV_TYPE(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 */
TLV_LEN(OspfRI.sr_info.msd) = htons(sizeof(uint32_t));
OspfRI.sr_info.msd.value = msd;
- return;
}
/* Unset this router MSD */
-static void unset_sr_node_msd()
+static void unset_sr_node_msd(void)
{
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)
/* Sanity Check */
if (lsa == NULL) {
- zlog_warn("OSPF-RI (ospf_router_info_lsa_update): Abort! LSA is NULL");
+ zlog_warn("OSPF-RI (%s): Abort! LSA is NULL", __func__);
return -1;
}
return 0;
/* Process only Router Information LSA */
- if (GET_OPAQUE_TYPE(
- ntohl(lsa->data->id.s_addr)) != OPAQUE_TYPE_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 */
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++) {
#define RI_STUB_SUPPORT 0x20000000
#define RI_TE_SUPPORT 0x10000000
#define RI_P2P_OVER_LAN 0x08000000
-#define RI_TE_EXPERIMENTAL 0x04000000
+#define RI_TE_EXPERIMENTA 0x04000000
#define RI_TLV_LENGTH 4
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, uint8_t);
+extern void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb,
+ uint8_t msd);
extern struct scope_info ospf_router_info_get_flooding_scope(void);
#endif /* _ZEBRA_OSPF_ROUTER_INFO_H */
/*
* This is an implementation of Segment Routing
- * as per draft-ietf-ospf-segment-routing-extensions-24
+ * as per draft draft-ietf-ospf-segment-routing-extensions-24
*
* Module name: Segment Routing
*
- * Author: Anselme Sawadogo <anselmesawadogo@gmail.com>
* 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.
+ * Copyright (C) 2016 - 2018 Orange Labs http://www.orange.com
*
- * 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.
+ * This program 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 of the License, 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.
+ * This program 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.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <math.h>
{
const struct in_addr *rid = p;
- return (jhash_1word(rid->s_addr, 0));
+ return jhash_1word(rid->s_addr, 0);
}
/* Compare 2 Router ID hash entries based on SR Node */
const struct sr_node *srn = p1;
const struct in_addr *rid = p2;
- return (IPV4_ADDR_SAME(&srn->adv_router, rid));
+ return IPV4_ADDR_SAME(&srn->adv_router, rid);
}
/* Functions to remove an SR Link */
del_sid_nhlfe(srl->nhlfe[0]);
del_sid_nhlfe(srl->nhlfe[1]);
XFREE(MTYPE_OSPF_SR_PARAMS, val);
- return;
+
}
/* Functions to remove an SR Prefix */
del_sid_nhlfe(srp->nhlfe);
XFREE(MTYPE_OSPF_SR_PARAMS, val);
- return;
+
}
/* Allocate new Segment Routine node */
/* Sanity Check */
if (new == NULL) {
- zlog_err(
- "SR (ospf_sr_node_new):"
- "Abort! can't create new SR node");
+ zlog_err("SR (%s): Abort! can't create new SR node", __func__);
return NULL;
}
struct listnode *node;
struct route_node *rn;
struct sr_node *srn;
+ bool found;
/* Sanity check */
if (OspfSR.neighbors == NULL)
inet_ntoa(nexthop));
/* First, search neighbor Router ID for this nexthop */
- for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi))
- for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
- if ((nbr = rn->info))
+ found = false;
+ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
+ nbr = rn->info;
+ if ((nbr) && (IPV4_ADDR_SAME(&nexthop, &nbr->src))) {
+ found = true;
break;
+ }
+ }
+ if (found)
+ break;
+ }
- if (nbr == NULL)
+ if (!found)
return NULL;
if (IS_DEBUG_OSPF_SR)
int rc = 0;
if (IS_DEBUG_OSPF_SR)
- zlog_debug("SR (ospf_sr_start): Start Segment Routing");
+ zlog_debug("SR (%s): Start Segment Routing", __func__);
/* Initialize self SR Node */
srn = hash_get(OspfSR.neighbors, (void *)&(ospf->router_id),
OspfSR.self = srn;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("SR (ospf_sr_start): Update SR-DB from LSDB");
+ zlog_debug("SR (%s): Update SR-DB from LSDB", __func__);
/* Start by looking to Router Info & Extended LSA in lsdb */
if ((ospf != NULL) && (ospf->backbone != NULL)) {
return rc;
}
-/* Remove an SR Node in the SRDB */
-static void ospf_sr_node_nhlfe_del(struct hash_backet *backet, void *args)
-{
- struct sr_node *srn = (struct sr_node *)backet->data;
- struct listnode *node;
- struct sr_prefix *srp;
- struct sr_link *srl;
-
- /* Sanity Check */
- if (srn == NULL)
- return;
-
- if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- Delete all Prefix for SR Node %s",
- inet_ntoa(srn->adv_router));
-
- /* Remove Extended Prefix */
- for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp))
- del_sid_nhlfe(srp->nhlfe);
-
- if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- Delete all Link for SR Node %s",
- inet_ntoa(srn->adv_router));
-
- /* Remove Extended Link */
- for (ALL_LIST_ELEMENTS_RO(srn->ext_link, node, srl)) {
- /* Remove NHLFE entries for this Link */
- del_sid_nhlfe(srl->nhlfe[0]);
- del_sid_nhlfe(srl->nhlfe[1]);
- }
-
- if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- Remove SR Node %s",
- inet_ntoa(srn->adv_router));
-}
-
/* Stop Segment Routing */
static void ospf_sr_stop(void)
{
if (IS_DEBUG_OSPF_SR)
- zlog_debug("SR (ospf_sr_stop): Stop Segment Routing");
-
- /* Start by removing all Prefix and Link for each SR Node */
- hash_iterate(OspfSR.neighbors, (void (*)(struct hash_backet *,
- void *))ospf_sr_node_nhlfe_del,
- NULL);
+ zlog_debug("SR (%s): Stop Segment Routing", __func__);
- /* Finish by cleaning the hash table */
+ /*
+ * Remove all SR Nodes from the Hash table. Prefix and Link SID will
+ * be remove though list_delete_and_null() call. See sr_node_del()
+ */
hash_clean(OspfSR.neighbors, (void *)sr_node_del);
}
{
int rc = -1;
- zlog_info("SR (ospf_sr_init): Initialize SR Data Base");
+ zlog_info("SR (%s): Initialize SR Data Base", __func__);
memset(&OspfSR, 0, sizeof(struct ospf_sr_db));
OspfSR.enabled = false;
OspfSR.srgb.range_size = MPLS_DEFAULT_MAX_SRGB_SIZE;
OspfSR.srgb.lower_bound = MPLS_DEFAULT_MIN_SRGB_LABEL;
- OspfSR.msd = MPLS_MAX_LABELS;
+ OspfSR.msd = 0;
/* Initialize Hash table for neighbor SR nodes */
OspfSR.neighbors = hash_create(sr_hash, sr_cmp, "OSPF_SR");
return NULL;
for (ALL_LIST_ELEMENTS_RO(top->oiflist, node, oi))
- for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
- if ((nbr = rn->info))
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
+ nbr = rn->info;
+ if (nbr)
if (IPV4_ADDR_SAME(&nbr->address.u.prefix4,
&addr)
|| IPV4_ADDR_SAME(&nbr->router_id, &addr)) {
route_unlock_node(rn);
return nbr;
}
-
+ }
return NULL;
}
static struct ospf_path *get_nexthop_by_addr(struct ospf *top,
struct prefix_ipv4 p)
{
- struct ospf_route * or ;
+ struct ospf_route *or;
struct ospf_path *path;
struct listnode *node;
struct route_node *rn;
return NULL;
if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- Search Nexthop for prefix %s/%d",
+ zlog_debug(" |- Search Nexthop for prefix %s/%u",
inet_ntoa(p.prefix), p.prefixlen);
rn = route_node_lookup(top->new_table, (struct prefix *)&p);
- /* Check if we found an OSPF route. May be NULL if SPF has not
- * yet populate routing table for this prefix. */
+ /*
+ * Check if we found an OSPF route. May be NULL if SPF has not
+ * yet populate routing table for this prefix.
+ */
if (rn == NULL)
return NULL;
route_unlock_node(rn);
-
- if ((or = rn->info) == NULL)
+ or = rn->info;
+ if (or == NULL)
return NULL;
/* Then search path from this route */
int rc = 0;
if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- Compute NHLFE for link %s/%d",
+ zlog_debug(" |- Compute NHLFE for link %s/%u",
inet_ntoa(srl->nhlfe[0].prefv4.prefix),
srl->nhlfe[0].prefv4.prefixlen);
int rc = -1;
if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- Compute NHLFE for prefix %s/%d",
+ zlog_debug(" |- Compute NHLFE for prefix %s/%u",
inet_ntoa(srp->nhlfe.prefv4.prefix),
srp->nhlfe.prefv4.prefixlen);
zlog_debug(" |- Found new next hop for this NHLFE: %s",
inet_ntoa(nh->nexthop));
- /* Get SR-Node for this nexthop */
+ /*
+ * Get SR-Node for this nexthop. Could be not yet available
+ * as Extende Link / Prefix and Router Information are flooded
+ * after LSA Type 1 & 2 which populate the OSPF Route Table
+ */
srnext = get_sr_node_by_nexthop(top, nh->nexthop);
- /* and store this information for later SRGB update */
+ if (srnext == NULL)
+ return rc;
+
+ /* And store this information for later update if SR Node is found */
srnext->neighbor = OspfSR.self;
if (IPV4_ADDR_SAME(&srnext->adv_router, &srp->adv_router))
srp->nexthop = NULL;
return rc;
if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- Found SRGB %d/%d for next hop SR-Node %s",
+ zlog_debug(" |- Found SRGB %u/%u for next hop SR-Node %s",
srnext->srgb.range_size, srnext->srgb.lower_bound,
inet_ntoa(srnext->adv_router));
/* Compute Input Label with self SRGB */
srp->nhlfe.label_in = index2label(srp->sid, OspfSR.srgb);
- /* and Output Label with Next hop SR Node SRGB or Implicit Null label
- * if next hop is the destination and request PHP */
+ /*
+ * and Output Label with Next hop SR Node SRGB or Implicit Null label
+ * if next hop is the destination and request PHP
+ */
if ((srp->nexthop == NULL)
&& (!CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)))
srp->nhlfe.label_out = MPLS_IMP_NULL_LABEL;
srp->nhlfe.label_out = index2label(srp->sid, srnext->srgb);
if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- Computed new labels in: %d out: %d",
+ zlog_debug(" |- Computed new labels in: %u out: %u",
srp->nhlfe.label_in, srp->nhlfe.label_out);
rc = 1;
stream_putw_at(s, 0, stream_get_endp(s));
if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- %s LSP %d/%d for %s/%d via %d",
+ zlog_debug(" |- %s LSP %u/%u for %s/%u via %u",
cmd == ZEBRA_MPLS_LABELS_ADD ? "Add" : "Delete",
nhlfe.label_in, nhlfe.label_out,
inet_ntoa(nhlfe.prefv4.prefix),
nhlfe.prefv4.prefixlen, nhlfe.ifindex);
- return (zclient_send_message(zclient));
+ return zclient_send_message(zclient);
}
/* Request zebra to install/remove FEC in FIB */
}
if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- %s FEC %d for %s/%d via %d",
+ zlog_debug(" |- %s FEC %u for %s/%u via %u",
cmd == ZEBRA_ROUTE_ADD ? "Add" : "Delete",
nhlfe.label_out, inet_ntoa(nhlfe.prefv4.prefix),
nhlfe.prefv4.prefixlen, nhlfe.ifindex);
- return (zclient_route_send(cmd, zclient, &api));
+ return zclient_route_send(cmd, zclient, &api);
}
/* Add new NHLFE entry for SID */
apply_mask_ipv4(&srl->nhlfe[1].prefv4);
if (IS_DEBUG_OSPF_SR) {
- zlog_debug(" |- Found primary Adj/Lan Sid %d for %s/%d",
+ zlog_debug(" |- Found primary Adj/Lan Sid %u for %s/%u",
srl->sid[0], inet_ntoa(srl->nhlfe[0].prefv4.prefix),
srl->nhlfe[0].prefv4.prefixlen);
- zlog_debug(" |- Found backup Adj/Lan Sid %d for %s/%d",
+ zlog_debug(" |- Found backup Adj/Lan Sid %u for %s/%u",
srl->sid[1], inet_ntoa(srl->nhlfe[1].prefv4.prefix),
srl->nhlfe[1].prefv4.prefixlen);
}
psid = (struct ext_subtlv_prefix_sid *)sub_tlvh;
if (psid->algorithm != SR_ALGORITHM_SPF) {
zlog_err(
- "SR (get_ext_prefix_sid): "
- "Unsupported Algorithm");
+ "SR (%s): Unsupported Algorithm",
+ __func__);
XFREE(MTYPE_OSPF_SR_PARAMS, srp);
return NULL;
}
}
if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- Found SID %d for prefix %s/%d", srp->sid,
+ zlog_debug(" |- Found SID %u for prefix %s/%u", srp->sid,
inet_ntoa(srp->nhlfe.prefv4.prefix),
srp->nhlfe.prefv4.prefixlen);
return srp;
}
if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- %s SR Link 8.0.0.%d for SR node %s",
+ zlog_debug(" |- %s SR Link 8.0.0.%u for SR node %s",
found ? "Update" : "Add",
GET_OPAQUE_ID(srl->instance),
inet_ntoa(srn->adv_router));
&srn->adv_router);
listnode_add(srn->ext_link, srl);
} else {
+ /* New NHLFE was not found.
+ * Just free the SR Link
+ */
XFREE(MTYPE_OSPF_SR_PARAMS, srl);
}
} else {
- /* This is just an LSA refresh.
- * Stop processing and free SR Link */
+ /*
+ * This is just an LSA refresh.
+ * Stop processing and free SR Link
+ */
XFREE(MTYPE_OSPF_SR_PARAMS, srl);
}
}
return;
if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- Process Extended Prefix SID %d", srp->sid);
+ zlog_debug(" |- Process Extended Prefix SID %u", srp->sid);
/* Process only Global Prefix SID */
if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_LFLG))
}
if (IS_DEBUG_OSPF_SR)
- zlog_debug(" |- %s SR LSA ID 7.0.0.%d for SR node %s",
+ zlog_debug(" |- %s SR LSA ID 7.0.0.%u for SR node %s",
found ? "Update" : "Add",
GET_OPAQUE_ID(srp->instance),
inet_ntoa(srn->adv_router));
IPV4_ADDR_COPY(&srp->adv_router, &srn->adv_router);
listnode_add(srn->ext_prefix, srp);
/* Try to set MPLS table */
- if (compute_prefix_nhlfe(srp) == 1) {
+ if (compute_prefix_nhlfe(srp) == 1)
add_sid_nhlfe(srp->nhlfe);
- }
} else {
if (sr_prefix_cmp(pref, srp)) {
if (compute_prefix_nhlfe(srp) == 1) {
listnode_add(srn->ext_prefix, srp);
} else {
/* New NHLFE was not found.
- * Just free the SR Prefix */
+ * Just free the SR Prefix
+ */
XFREE(MTYPE_OSPF_SR_PARAMS, srp);
}
} else {
/* This is just an LSA refresh.
- * Stop processing and free SR Prefix */
+ * Stop processing and free SR Prefix
+ */
XFREE(MTYPE_OSPF_SR_PARAMS, srp);
}
}
struct sr_prefix *srp;
struct sr_nhlfe new;
- /* Skip Self Node */
- if (srn == OspfSR.self)
- return;
-
/* Process Every Extended Prefix for this SR-Node */
for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
+ /* Process Self SRN only if NO-PHP is requested */
+ if ((srn == OspfSR.self)
+ && !CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG))
+ continue;
+
/* Process only SID Index */
if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_VFLG))
continue;
- /* Compute new NHLFE */
+
+ /* OK. Compute new NHLFE */
memcpy(&new, &srp->nhlfe, sizeof(struct sr_nhlfe));
new.label_in = index2label(srp->sid, OspfSR.srgb);
/* Update MPLS LFIB */
if (IS_DEBUG_OSPF_SR)
zlog_debug(
- "SR (ospf_sr_ri_lsa_update): Process Router "
- "Information LSA 4.0.0.%d from %s",
+ "SR (%s): Process Router "
+ "Information LSA 4.0.0.%u from %s",
+ __func__,
GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
inet_ntoa(lsah->adv_router));
return;
if (OspfSR.neighbors == NULL) {
- zlog_err(
- "SR (ospf_sr_ri_lsa_update): Abort! no valid "
- "SR DataBase");
+ zlog_err("SR (%s): Abort! no valid SR DataBase", __func__);
return;
}
/* Sanity check */
if (srn == NULL) {
zlog_err(
- "SR (ospf_sr_ri_lsa_update): Abort! can't create "
- "SR node in hash table");
+ "SR (%s): Abort! can't create SR node in hash table",
+ __func__);
return;
}
if ((srn->instance != 0) && (srn->instance != ntohl(lsah->id.s_addr))) {
zlog_err(
- "SR (ospf_sr_ri_lsa_update): Abort! Wrong "
- "LSA ID 4.0.0.%d for SR node %s/%d",
+ "SR (%s): Abort! Wrong "
+ "LSA ID 4.0.0.%u for SR node %s/%u",
+ __func__,
GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
inet_ntoa(lsah->adv_router), srn->instance);
return;
case RI_SR_TLV_SR_ALGORITHM:
algo = (struct ri_sr_tlv_sr_algorithm *)tlvh;
int i;
+
for (i = 0; i < ntohs(algo->header.length); i++)
srn->algo[i] = algo->value[0];
for (; i < ALGORITHM_COUNT; i++)
if (srn->algo[0] == SR_ALGORITHM_UNSET || srgb.range_size == 0
|| srgb.lower_bound == 0) {
zlog_warn(
- "SR (ospf_sr_ri_lsa_update): Missing "
- "mandatory parameters. Abort!");
+ "SR (%s): Missing mandatory parameters. Abort!",
+ __func__);
hash_release(OspfSR.neighbors, &(srn->adv_router));
XFREE(MTYPE_OSPF_SR_PARAMS, srn);
return;
(void *)srn);
}
- return;
}
/*
if (IS_DEBUG_OSPF_SR)
zlog_debug(
- "SR (ospf_sr_ri_lsa_delete): Remove SR node %s "
- "from lsa_id 4.0.0.%d",
- inet_ntoa(lsah->adv_router),
+ "SR (%s): Remove SR node %s from lsa_id 4.0.0.%u",
+ __func__, inet_ntoa(lsah->adv_router),
GET_OPAQUE_ID(ntohl(lsah->id.s_addr)));
/* Sanity check */
if (OspfSR.neighbors == NULL) {
- zlog_err(
- "SR (ospf_sr_ri_lsa_delete): Abort! no valid "
- "SR Data Base");
+ zlog_err("SR (%s): Abort! no valid SR Data Base", __func__);
return;
}
/* Sanity check */
if (srn == NULL) {
zlog_err(
- "SR (ospf_sr_ri_lsa_delete): Abort! no entry in SRDB "
- "for SR Node %s",
- inet_ntoa(lsah->adv_router));
+ "SR (%s): Abort! no entry in SRDB for SR Node %s",
+ __func__, inet_ntoa(lsah->adv_router));
return;
}
if ((srn->instance != 0) && (srn->instance != ntohl(lsah->id.s_addr))) {
zlog_err(
- "SR (ospf_sr_ri_lsa_delete): Abort! Wrong "
- "LSA ID 4.0.0.%d for SR node %s",
- GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
+ "SR (%s): Abort! Wrong LSA ID 4.0.0.%u for SR node %s",
+ __func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
inet_ntoa(lsah->adv_router));
return;
}
/* Remove SR node */
sr_node_del(srn);
- return;
}
/* Update Segment Routing from Extended Link LSA */
if (IS_DEBUG_OSPF_SR)
zlog_debug(
- "SR (ospf_sr_ext_link_lsa_update): Process "
- "Extended Link LSA 8.0.0.%d from %s",
- GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
+ "SR (%s): Process Extended Link LSA 8.0.0.%u from %s",
+ __func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
inet_ntoa(lsah->adv_router));
/* Sanity check */
if (OspfSR.neighbors == NULL) {
- zlog_err(
- "SR (ospf_sr_ext_link_lsa_update): Abort! no "
- "valid SR DataBase");
+ zlog_err("SR (%s): Abort! no valid SR DataBase", __func__);
return;
}
/* Sanity check */
if (srn == NULL) {
zlog_err(
- "SR (ospf_sr_ext_link_lsa_update): Abort! can't "
- "create SR node in hash table");
+ "SR (%s): Abort! can't create SR node in hash table",
+ __func__);
return;
}
if (IS_DEBUG_OSPF_SR)
zlog_debug(
- "SR (ospf_sr_ext_link_lsa_delete): Remove "
- "Extended Link LSA 8.0.0.%d from %s",
- GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
+ "SR (%s): Remove Extended Link LSA 8.0.0.%u from %s",
+ __func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
inet_ntoa(lsah->adv_router));
/* Sanity check */
if (OspfSR.neighbors == NULL) {
- zlog_err(
- "SR (ospf_sr_ext_link_lsa_delete): Abort! no "
- "valid SR DataBase");
+ zlog_err("SR (%s): Abort! no valid SR DataBase", __func__);
return;
}
srn = (struct sr_node *)hash_lookup(OspfSR.neighbors,
(void *)&(lsah->adv_router));
- /* SR-Node may be NULL if it has been remove previously when
- * processing Router Information LSA deletion */
+ /*
+ * SR-Node may be NULL if it has been remove previously when
+ * processing Router Information LSA deletion
+ */
if (srn == NULL) {
zlog_warn(
- "SR (ospf_sr_ext_link_lsa_delete): Stop! "
- "no entry in SRDB for SR Node %s",
- inet_ntoa(lsah->adv_router));
+ "SR (%s): Stop! no entry in SRDB for SR Node %s",
+ __func__, inet_ntoa(lsah->adv_router));
return;
}
XFREE(MTYPE_OSPF_SR_PARAMS, srl);
} else {
zlog_warn(
- "SR (ospf_sr_ext_link_lsa_delete): Didn't "
- "found corresponding SR Link 8.0.0.%d for SR Node %s",
+ "SR (%s): Didn't found corresponding SR Link 8.0.0.%u "
+ "for SR Node %s", __func__,
GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
inet_ntoa(lsah->adv_router));
}
- return;
}
/* Update Segment Routing from Extended Prefix LSA */
if (IS_DEBUG_OSPF_SR)
zlog_debug(
- "SR (ospf_sr_ext_prefix_lsa_update): Process "
- "Extended Prefix LSA 7.0.0.%d from %s",
+ "SR (%s): Process Extended Prefix LSA "
+ "7.0.0.%u from %s", __func__,
GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
inet_ntoa(lsah->adv_router));
/* Sanity check */
if (OspfSR.neighbors == NULL) {
- zlog_err(
- "SR (ospf_sr_ext_prefix_lsa_update): Abort! no "
- "valid SR DataBase");
+ zlog_err("SR (%s): Abort! no valid SR DataBase", __func__);
return;
}
/* Sanity check */
if (srn == NULL) {
zlog_err(
- "SR (ospf_sr_ext_prefix_lsa_update): Abort! can't "
- "create SR node in hash table");
+ "SR (%s): Abort! can't create SR node in hash table",
+ __func__);
return;
}
if (IS_DEBUG_OSPF_SR)
zlog_debug(
- "SR (ospf_sr_ext_prefix_lsa_delete): Remove "
- "Extended Prefix LSA 7.0.0.%d from %s",
- GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
+ "SR (%s): Remove Extended Prefix LSA 7.0.0.%u from %s",
+ __func__, GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
inet_ntoa(lsah->adv_router));
/* Sanity check */
if (OspfSR.neighbors == NULL) {
- zlog_err(
- "SR (ospf_sr_ext_prefix_lsa_delete): Abort! no "
- "valid SR DataBase");
+ zlog_err("SR (%s): Abort! no valid SR DataBase", __func__);
return;
}
srn = (struct sr_node *)hash_lookup(OspfSR.neighbors,
(void *)&(lsah->adv_router));
- /* SR-Node may be NULL if it has been remove previously when
- * processing Router Information LSA deletion */
+ /*
+ * SR-Node may be NULL if it has been remove previously when
+ * processing Router Information LSA deletion
+ */
if (srn == NULL) {
zlog_warn(
- "SR (ospf_sr_ext_prefix_lsa_delete): Stop! "
- "no entry in SRDB for SR Node %s",
- inet_ntoa(lsah->adv_router));
+ "SR (%s): Stop! no entry in SRDB for SR Node %s",
+ __func__, inet_ntoa(lsah->adv_router));
return;
}
XFREE(MTYPE_OSPF_SR_PARAMS, srp);
} else {
zlog_warn(
- "SR (ospf_sr_ext_prefix_lsa_delete): Didn't found"
- "corresponding SR Prefix 7.0.0.%d for SR Node %s",
+ "SR (%s): Didn't found corresponding SR Prefix "
+ "7.0.0.%u for SR Node %s", __func__,
GET_OPAQUE_ID(ntohl(lsah->id.s_addr)),
inet_ntoa(lsah->adv_router));
}
- return;
}
/* Get Label for Extended Link SID */
return label;
}
+/*
+ * Update Prefix SID. Call by ospf_ext_pref_ism_change to
+ * complete initial CLI command at startutp.
+ *
+ * @param ifp - Loopback interface
+ * @param pref - Prefix address of this interface
+ *
+ * @return - void
+ */
+void ospf_sr_update_prefix(struct interface *ifp, struct prefix *p)
+{
+ struct listnode *node;
+ struct sr_prefix *srp;
+ uint32_t rc;
+
+ /* Sanity Check */
+ if ((ifp == NULL) || (p == NULL))
+ return;
+
+ /*
+ * Search if there is a Segment Prefix that correspond to this
+ * interface or prefix, and update it if found
+ */
+ for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node, srp)) {
+ if ((srp->nhlfe.ifindex == ifp->ifindex)
+ || ((IPV4_ADDR_SAME(&srp->nhlfe.prefv4.prefix,
+ &p->u.prefix4))
+ && (srp->nhlfe.prefv4.prefixlen == p->prefixlen))) {
+
+ /* Update Interface & Prefix info */
+ srp->nhlfe.ifindex = ifp->ifindex;
+ IPV4_ADDR_COPY(&srp->nhlfe.prefv4.prefix,
+ &p->u.prefix4);
+ srp->nhlfe.prefv4.prefixlen = p->prefixlen;
+ srp->nhlfe.prefv4.family = p->family;
+ IPV4_ADDR_COPY(&srp->nhlfe.nexthop, &p->u.prefix4);
+
+ /* OK. Let's Schedule Extended Prefix LSA */
+ rc = ospf_ext_schedule_prefix_index(ifp, srp->sid,
+ &srp->nhlfe.prefv4, srp->flags);
+ srp->instance = SET_OPAQUE_LSID(
+ OPAQUE_TYPE_EXTENDED_PREFIX_LSA, rc);
+
+ /* Install NHLFE if NO-PHP is requested */
+ if (CHECK_FLAG(srp->flags,
+ EXT_SUBTLV_PREFIX_SID_NPFLG)) {
+ srp->nhlfe.label_in = index2label(srp->sid,
+ OspfSR.self->srgb);
+ srp->nhlfe.label_out = MPLS_IMP_NULL_LABEL;
+ add_sid_nhlfe(srp->nhlfe);
+ }
+ }
+ }
+}
+
/*
* Following functions are used to update MPLS LFIB after a SPF run
*/
struct listnode *node;
struct sr_prefix *srp;
struct sr_nhlfe old;
- struct interface *ifp;
- struct prefix p;
int rc;
/* Sanity Check */
zlog_debug(" |- Update Prefix for SR Node %s",
inet_ntoa(srn->adv_router));
- /* For FRR router check if there is no SR Prefix
- * waiting to be communicated to Extended Prefix */
- if (srn == OspfSR.self) {
- for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
-
- /* Skip Prefix already engaged */
- if (srp->instance != 0)
- continue;
- /* Get Interface and check if it is a Loopback */
- p.family = AF_INET;
- p.prefixlen = srp->nhlfe.prefv4.prefixlen;
- IPV4_ADDR_COPY(&p.u.prefix4, &srp->nhlfe.prefv4.prefix);
- ifp = if_lookup_prefix(&p, VRF_DEFAULT);
- if (ifp == NULL)
- continue;
- /* If interface is not a loopback, remove SR prefix */
- if (!if_is_loopback(ifp)) {
- zlog_warn(
- " |- Interface %s is not a "
- "Loopback. Remove prefix",
- ifp->name);
- listnode_delete(srn->ext_prefix, srp);
- XFREE(MTYPE_OSPF_SR_PARAMS, srp);
- continue;
- }
- /* OK. Let's update Extended Prefix LSA */
- rc = ospf_ext_schedule_prefix_index(ifp, srp->sid,
- &srp->nhlfe.prefv4);
- srp->instance = SET_OPAQUE_LSID(
- OPAQUE_TYPE_EXTENDED_PREFIX_LSA, rc);
- srp->nhlfe.ifindex = ifp->ifindex;
- }
+ /* Skip Self SR Node */
+ if (srn == OspfSR.self)
return;
- }
/* Update Extended Prefix */
for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
monotime(&start_time);
if (IS_DEBUG_OSPF_SR)
- zlog_debug("SR (ospf_sr_update_schedule): Start SPF update");
+ zlog_debug("SR (%s): Start SPF update", __func__);
hash_iterate(OspfSR.neighbors, (void (*)(struct hash_backet *,
void *))ospf_sr_nhlfe_update,
monotime(&stop_time);
zlog_info(
- "SR (ospf_sr_update_schedule): SPF Processing Time(usecs): "
- "%lld\n",
+ "SR (%s): SPF Processing Time(usecs): %lld\n",
+ __func__,
(stop_time.tv_sec - start_time.tv_sec) * 1000000LL
+ (stop_time.tv_usec - start_time.tv_usec));
OSPF_SR_UPDATE_INTERVAL, &ospf->t_sr_update);
}
-/*------------------------------------------------------------------------*
+/*
+ * --------------------------------------
* Followings are vty command functions.
- *------------------------------------------------------------------------*/
+ * --------------------------------------
+ */
/*
* Segment Routing Router configuration
if (OspfSR.enabled) {
vty_out(vty, " segment-routing on\n");
- vty_out(vty, " segment-routing global-block %d %d\n",
- OspfSR.srgb.lower_bound,
- OspfSR.srgb.lower_bound + OspfSR.srgb.range_size - 1);
-
+ if ((OspfSR.srgb.lower_bound != MPLS_DEFAULT_MIN_SRGB_LABEL)
+ || (OspfSR.srgb.range_size != MPLS_DEFAULT_MAX_SRGB_SIZE)) {
+ vty_out(vty, " segment-routing global-block %u %u\n",
+ OspfSR.srgb.lower_bound,
+ OspfSR.srgb.lower_bound +
+ OspfSR.srgb.range_size - 1);
+ }
if (OspfSR.msd != 0)
- vty_out(vty, " segment-routing node-msd %d\n",
+ vty_out(vty, " segment-routing node-msd %u\n",
OspfSR.msd);
if (OspfSR.self != NULL) {
for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node,
srp)) {
vty_out(vty,
- " segment-routing prefix %s/%d "
- "index %d\n",
+ " segment-routing prefix %s/%u "
+ "index %u%s\n",
inet_ntoa(srp->nhlfe.prefv4.prefix),
- srp->nhlfe.prefv4.prefixlen, srp->sid);
+ srp->nhlfe.prefv4.prefixlen, srp->sid,
+ CHECK_FLAG(srp->flags,
+ EXT_SUBTLV_PREFIX_SID_NPFLG) ?
+ " no-php-flag" : "");
}
}
}
if (!ospf_sr_enabled(vty))
return CMD_WARNING_CONFIG_FAILED;
- if (sscanf(argv[idx_low]->arg, "%d", &lower) != 1) {
- vty_out(vty, "segment-routing: fscanf: %s\n",
- safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (sscanf(argv[idx_up]->arg, "%d", &upper) != 1) {
- vty_out(vty, "segment-routing: fscanf: %s\n",
- safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
+ /* Get lower and upper bound */
+ lower = strtoul(argv[idx_low]->arg, NULL, 10);
+ upper = strtoul(argv[idx_up]->arg, NULL, 10);
size = upper - lower + 1;
if (size > MPLS_DEFAULT_MAX_SRGB_SIZE || size <= 0) {
vty_out(vty,
- "Range size cannot be less than 0 or more than %d\n",
+ "Range size cannot be less than 0 or more than %u\n",
MPLS_DEFAULT_MAX_SRGB_SIZE);
return CMD_WARNING_CONFIG_FAILED;
}
if (upper > MPLS_DEFAULT_MAX_SRGB_LABEL) {
- vty_out(vty, "Upper-bound cannot exceed %d\n",
+ vty_out(vty, "Upper-bound cannot exceed %u\n",
MPLS_DEFAULT_MAX_SRGB_LABEL);
return CMD_WARNING_CONFIG_FAILED;
}
if (upper < MPLS_DEFAULT_MIN_SRGB_LABEL) {
- vty_out(vty, "Upper-bound cannot be lower than %d\n",
+ vty_out(vty, "Upper-bound cannot be lower than %u\n",
MPLS_DEFAULT_MIN_SRGB_LABEL);
return CMD_WARNING_CONFIG_FAILED;
}
+ /* Check if values have changed */
+ if ((OspfSR.srgb.range_size == size)
+ && (OspfSR.srgb.lower_bound == lower))
+ return CMD_SUCCESS;
+
/* Set SID/Label range SRGB */
OspfSR.srgb.range_size = size;
OspfSR.srgb.lower_bound = lower;
+ if (OspfSR.self != NULL) {
+ OspfSR.self->srgb.range_size = size;
+ OspfSR.self->srgb.lower_bound = lower;
+ }
/* Set Router Information SR parameters */
ospf_router_info_update_sr(true, OspfSR.srgb, OspfSR.msd);
DEFUN (no_sr_sid_label_range,
no_sr_sid_label_range_cmd,
- "no segment-routing global-block",
+ "no segment-routing global-block [(0-1048575) (0-1048575)]",
NO_STR
SR_STR
- "Delete Segment Routing Global Block label range\n")
+ "Segment Routing Global Block label range\n"
+ "Lower-bound range in decimal (0-1048575)\n"
+ "Upper-bound range in decimal (0-1048575)\n")
{
if (!ospf_sr_enabled(vty))
/* Revert to default SRGB value */
OspfSR.srgb.range_size = MPLS_DEFAULT_MIN_SRGB_SIZE;
OspfSR.srgb.lower_bound = MPLS_DEFAULT_MIN_SRGB_LABEL;
+ if (OspfSR.self != NULL) {
+ OspfSR.self->srgb.range_size = OspfSR.srgb.range_size;
+ OspfSR.self->srgb.lower_bound = OspfSR.srgb.lower_bound;
+ }
/* Set Router Information SR parameters */
ospf_router_info_update_sr(true, OspfSR.srgb, OspfSR.msd);
"Maximum number of label that could be stack (1-16)\n")
{
uint32_t msd;
- int idx_number = 2;
+ int idx;
if (!ospf_sr_enabled(vty))
return CMD_WARNING_CONFIG_FAILED;
- if (sscanf(argv[idx_number]->arg, "%d", &msd) != 1) {
- vty_out(vty, "segment-routing: fscanf: %s\n",
- safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
+ /* Get MSD */
+ argv_find(argv, argc, "(1-16)", &idx);
+ msd = strtoul(argv[idx]->arg, NULL, 10);
if (msd < 1 || msd > MPLS_MAX_LABELS) {
- vty_out(vty, "MSD must be comprise between 1 and %d\n",
+ vty_out(vty, "MSD must be comprise between 1 and %u\n",
MPLS_MAX_LABELS);
return CMD_WARNING_CONFIG_FAILED;
}
+ /* Check if value has changed */
+ if (OspfSR.msd == msd)
+ return CMD_SUCCESS;
+
/* Set this router MSD */
OspfSR.msd = msd;
+ if (OspfSR.self != NULL)
+ OspfSR.self->msd = msd;
/* Set Router Information SR parameters */
ospf_router_info_update_sr(true, OspfSR.srgb, OspfSR.msd);
DEFUN (no_sr_node_msd,
no_sr_node_msd_cmd,
- "no segment-routing node-msd",
+ "no segment-routing node-msd [(1-16)]",
NO_STR
SR_STR
- "Disable Maximum Stack Depth for this router\n")
+ "Maximum Stack Depth for this router\n"
+ "Maximum number of label that could be stack (1-16)\n")
{
if (!ospf_sr_enabled(vty))
/* unset this router MSD */
OspfSR.msd = 0;
+ if (OspfSR.self != NULL)
+ OspfSR.self->msd = 0;
/* Set Router Information SR parameters */
ospf_router_info_update_sr(true, OspfSR.srgb, 0);
DEFUN (sr_prefix_sid,
sr_prefix_sid_cmd,
- "segment-routing prefix A.B.C.D/M index (0-65535)",
+ "segment-routing prefix A.B.C.D/M index (0-65535) [no-php-flag]",
SR_STR
"Prefix SID\n"
"IPv4 Prefix as A.B.C.D/M\n"
"SID index for this prefix in decimal (0-65535)\n"
- "Index value inside SRGB (lower_bound < index < upper_bound)\n")
+ "Index value inside SRGB (lower_bound < index < upper_bound)\n"
+ "Don't request Penultimate Hop Popping (PHP)\n")
{
- int idx_prefix = 2;
- int idx_index = 4;
+ int idx = 0;
struct prefix p;
uint32_t index;
struct listnode *node;
struct sr_prefix *srp;
struct interface *ifp;
+ int rc;
if (!ospf_sr_enabled(vty))
return CMD_WARNING_CONFIG_FAILED;
/* Get network prefix */
- str2prefix(argv[idx_prefix]->arg, &p);
+ argv_find(argv, argc, "A.B.C.D/M", &idx);
+ rc = str2prefix(argv[idx]->arg, &p);
+ if (!rc) {
+ vty_out(vty, "Invalid prefix format %s\n",
+ argv[idx]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
/* Get & verify index value */
- index = strtoul(argv[idx_index]->arg, NULL, 10);
+ argv_find(argv, argc, "(0-65535)", &idx);
+ index = strtoul(argv[idx]->arg, NULL, 10);
if (index > OspfSR.srgb.range_size - 1) {
- vty_out(vty, "Index %d must be lower than range size %d\n",
+ vty_out(vty, "Index %u must be lower than range size %u\n",
index, OspfSR.srgb.range_size);
return CMD_WARNING_CONFIG_FAILED;
}
/* check that the index is not already used */
for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node, srp)) {
if (srp->sid == index) {
- vty_out(vty, "Index %d is already used\n", index);
+ vty_out(vty, "Index %u is already used\n", index);
return CMD_WARNING_CONFIG_FAILED;
}
}
+ /* Add new Extended Prefix to SRDB */
+ srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
+ IPV4_ADDR_COPY(&srp->nhlfe.prefv4.prefix, &p.u.prefix4);
+ IPV4_ADDR_COPY(&srp->nhlfe.nexthop, &p.u.prefix4);
+ srp->nhlfe.prefv4.prefixlen = p.prefixlen;
+ srp->nhlfe.prefv4.family = p.family;
+ srp->sid = index;
+ /* Set NO PHP flag if present */
+ if (argv_find(argv, argc, "no-php-flag", &idx))
+ SET_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG);
+ listnode_add(OspfSR.self->ext_prefix, srp);
+
+ if (IS_DEBUG_OSPF_SR)
+ zlog_debug(
+ "SR (%s): Add new Prefix %s/%u with index %u",
+ __func__, inet_ntoa(srp->nhlfe.prefv4.prefix),
+ srp->nhlfe.prefv4.prefixlen, index);
+
/* Get Interface and check if it is a Loopback */
ifp = if_lookup_prefix(&p, VRF_DEFAULT);
if (ifp == NULL) {
- /* Interface could be not yet available i.e. when this
+ /*
+ * Interface could be not yet available i.e. when this
* command is in the configuration file, OSPF is not yet
* ready. In this case, store the prefix SID for latter
- * (i.e. when SPF run) communication to Extended Prefix */
- srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix));
- srp->instance = 0;
- IPV4_ADDR_COPY(&srp->nhlfe.prefv4.prefix, &p.u.prefix4);
- srp->nhlfe.prefv4.prefixlen = p.prefixlen;
- srp->nhlfe.prefv4.family = p.family;
- srp->sid = index;
- listnode_add(OspfSR.self->ext_prefix, srp);
- vty_out(vty,
- "Interface for prefix %s not found. Deferred LSA "
- "flooding\n",
- argv[idx_prefix]->arg);
+ * update of this Extended Prefix
+ */
+ zlog_warn(
+ "Interface for prefix %s/%u not found. Deferred LSA "
+ "flooding", inet_ntoa(p.u.prefix4), p.prefixlen);
return CMD_SUCCESS;
}
+
if (!if_is_loopback(ifp)) {
vty_out(vty, "interface %s is not a Loopback\n", ifp->name);
+ listnode_delete(OspfSR.self->ext_prefix, srp);
+ XFREE(MTYPE_OSPF_SR_PARAMS, srp);
return CMD_WARNING_CONFIG_FAILED;
}
+ srp->nhlfe.ifindex = ifp->ifindex;
- /* Update Extended Prefix LSA */
- if (!ospf_ext_schedule_prefix_index(ifp, index,
- (struct prefix_ipv4 *)&p)) {
- vty_out(vty, "Unable to set index %d for prefix %s\n", index,
- argv[idx_prefix]->arg);
+ /* Install NHLFE if NO-PHP is requested */
+ if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)) {
+ srp->nhlfe.label_in = index2label(srp->sid, OspfSR.self->srgb);
+ srp->nhlfe.label_out = MPLS_IMP_NULL_LABEL;
+ add_sid_nhlfe(srp->nhlfe);
+ }
+
+ /* Finally, update Extended Prefix LSA */
+ rc = ospf_ext_schedule_prefix_index(ifp, srp->sid,
+ &srp->nhlfe.prefv4, srp->flags);
+ if (rc == 0) {
+ vty_out(vty, "Unable to set index %u for prefix %s/%u\n", index,
+ inet_ntoa(p.u.prefix4), p.prefixlen);
return CMD_WARNING;
}
+ srp->instance = SET_OPAQUE_LSID(OPAQUE_TYPE_EXTENDED_PREFIX_LSA, rc);
return CMD_SUCCESS;
}
DEFUN (no_sr_prefix_sid,
no_sr_prefix_sid_cmd,
- "no segment-routing prefix A.B.C.D/M",
+ "no segment-routing prefix A.B.C.D/M [index (0-65535) no-php-flag]",
NO_STR
SR_STR
"Prefix SID\n"
- "IPv4 Prefix as A.B.C.D/M\n")
+ "IPv4 Prefix as A.B.C.D/M\n"
+ "SID index for this prefix in decimal (0-65535)\n"
+ "Index value inside SRGB (lower_bound < index < upper_bound)\n"
+ "Don't request Penultimate Hop Popping (PHP)\n")
{
- int idx_prefix = 2;
+ int idx = 0;
struct prefix p;
struct listnode *node;
struct sr_prefix *srp;
struct interface *ifp;
bool found = false;
+ int rc;
/* Get network prefix */
- str2prefix(argv[idx_prefix]->arg, &p);
+ argv_find(argv, argc, "A.B.C.D/M", &idx);
+ rc = str2prefix(argv[idx]->arg, &p);
+ if (!rc) {
+ vty_out(vty, "Invalid prefix format %s\n",
+ argv[idx]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
/* check that the prefix is already set */
for (ALL_LIST_ELEMENTS_RO(OspfSR.self->ext_prefix, node, srp))
if (IPV4_ADDR_SAME(&srp->nhlfe.prefv4.prefix, &p.u.prefix4)
- && (srp->nhlfe.prefv4.prefixlen == p.prefixlen))
+ && (srp->nhlfe.prefv4.prefixlen == p.prefixlen)) {
found = true;
+ break;
+ }
if (!found) {
vty_out(vty, "Prefix %s is not found. Abort!\n",
- argv[idx_prefix]->arg);
+ argv[idx]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
- /* Get Interface and check if it is a Loopback */
- ifp = if_lookup_prefix(&p, VRF_DEFAULT);
+ /* Get Interface */
+ ifp = if_lookup_by_index(srp->nhlfe.ifindex, VRF_DEFAULT);
if (ifp == NULL) {
vty_out(vty, "interface for prefix %s not found.\n",
- argv[idx_prefix]->arg);
- return CMD_WARNING_CONFIG_FAILED;
- }
- if (!if_is_loopback(ifp)) {
- vty_out(vty, "interface %s is not a Loopback\n", ifp->name);
+ argv[idx]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
+
/* Update Extended Prefix LSA */
- if (!ospf_ext_schedule_prefix_index(ifp, 0, NULL)) {
+ if (!ospf_ext_schedule_prefix_index(ifp, 0, NULL, 0)) {
vty_out(vty, "No corresponding loopback interface. Abort!\n");
return CMD_WARNING;
}
+ if (IS_DEBUG_OSPF_SR)
+ zlog_debug(
+ "SR (%s): Remove Prefix %s/%u with index %u",
+ __func__, inet_ntoa(srp->nhlfe.prefv4.prefix),
+ srp->nhlfe.prefv4.prefixlen, srp->sid);
+
+ /* Delete NHLFE is NO-PHP is set */
+ if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG))
+ del_sid_nhlfe(srp->nhlfe);
+
+ /* OK, all is clean, remove SRP from SRDB */
+ listnode_delete(OspfSR.self->ext_prefix, srp);
+ XFREE(MTYPE_OSPF_SR_PARAMS, srp);
+
return CMD_SUCCESS;
}
+
+
static void show_vty_sr_node(struct vty *vty, struct sr_node *srn)
{
struct sr_prefix *srp;
struct interface *itf;
char pref[16];
- char sid[20];
+ char sid[22];
char label[8];
/* Sanity Check */
return;
vty_out(vty, "SR-Node: %s", inet_ntoa(srn->adv_router));
- vty_out(vty, "\tSRGB (Size/Label): %d/%d", srn->srgb.range_size,
+ vty_out(vty, "\tSRGB (Size/Label): %u/%u", srn->srgb.range_size,
srn->srgb.lower_bound);
vty_out(vty, "\tAlgorithm(s): %s",
srn->algo[0] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF");
srn->algo[i] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF");
}
if (srn->msd != 0)
- vty_out(vty, "\tMSD: %d", srn->msd);
+ vty_out(vty, "\tMSD: %u", srn->msd);
vty_out(vty,
- "\n\n Prefix or Link Label In Label Out "
+ "\n\n Prefix or Link Label In Label Out "
"Node or Adj. SID Interface Nexthop\n");
vty_out(vty,
"------------------ -------- --------- "
- "-------------------- --------- ---------------\n");
+ "--------------------- --------- ---------------\n");
for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
strncpy(pref, inet_ntoa(srp->nhlfe.prefv4.prefix), 16);
- snprintf(sid, 20, "SR Pfx (idx %d)", srp->sid);
+ snprintf(sid, 22, "SR Pfx (idx %u)", srp->sid);
if (srp->nhlfe.label_out == MPLS_IMP_NULL_LABEL)
sprintf(label, "pop");
else
- sprintf(label, "%d", srp->nhlfe.label_out);
+ sprintf(label, "%u", srp->nhlfe.label_out);
itf = if_lookup_by_index(srp->nhlfe.ifindex, VRF_DEFAULT);
- vty_out(vty, "%15s/%d %8d %9s %20s %9s %15s\n", pref,
+ vty_out(vty, "%15s/%u %8u %9s %21s %9s %15s\n", pref,
srp->nhlfe.prefv4.prefixlen, srp->nhlfe.label_in, label,
sid, itf ? itf->name : "-",
inet_ntoa(srp->nhlfe.nexthop));
for (ALL_LIST_ELEMENTS_RO(srn->ext_link, node, srl)) {
strncpy(pref, inet_ntoa(srl->nhlfe[0].prefv4.prefix), 16);
- snprintf(sid, 20, "SR Adj. (lbl %d)", srl->sid[0]);
+ snprintf(sid, 22, "SR Adj. (lbl %u)", srl->sid[0]);
if (srl->nhlfe[0].label_out == MPLS_IMP_NULL_LABEL)
sprintf(label, "pop");
else
- sprintf(label, "%d", srl->nhlfe[0].label_out);
+ sprintf(label, "%u", srl->nhlfe[0].label_out);
itf = if_lookup_by_index(srl->nhlfe[0].ifindex, VRF_DEFAULT);
- vty_out(vty, "%15s/%d %8d %9s %20s %9s %15s\n", pref,
+ vty_out(vty, "%15s/%u %8u %9s %21s %9s %15s\n", pref,
srl->nhlfe[0].prefv4.prefixlen, srl->nhlfe[0].label_in,
label, sid, itf ? itf->name : "-",
inet_ntoa(srl->nhlfe[0].nexthop));
- snprintf(sid, 20, "SR Adj. (lbl %d)", srl->sid[1]);
+ snprintf(sid, 22, "SR Adj. (lbl %u)", srl->sid[1]);
if (srl->nhlfe[1].label_out == MPLS_IMP_NULL_LABEL)
sprintf(label, "pop");
else
- sprintf(label, "%d", srl->nhlfe[0].label_out);
- vty_out(vty, "%15s/%d %8d %9s %20s %9s %15s\n", pref,
+ sprintf(label, "%u", srl->nhlfe[0].label_out);
+ vty_out(vty, "%15s/%u %8u %9s %21s %9s %15s\n", pref,
srl->nhlfe[1].prefv4.prefixlen, srl->nhlfe[1].label_in,
label, sid, itf ? itf->name : "-",
inet_ntoa(srl->nhlfe[1].nexthop));
"Advertising SR node ID (as an IP address)\n"
"Self-originated SR node\n")
{
- int idx_ip = 6;
+ int idx = 0;
struct in_addr rid;
struct sr_node *srn;
vty_out(vty, "\n OSPF Segment Routing database for ID %s\n\n",
inet_ntoa(OspfSR.self->adv_router));
- if (argc < idx_ip) {
- /* Iterate through all the SRDB */
- hash_iterate(
- OspfSR.neighbors,
- (void (*)(struct hash_backet *, void *))show_srdb_entry,
- (void *)vty);
- } else {
- /* or show only specified SR Node */
- if (argc == idx_ip) {
- srn = OspfSR.self;
- } else {
- if (!inet_aton(argv[idx_ip]->arg, &rid)) {
- vty_out(vty,
- "Specified Router ID %s is "
- "invalid\n",
- argv[idx_ip]->arg);
- return CMD_WARNING_CONFIG_FAILED;
- }
- /* Get the SR Node from the SRDB */
- srn = (struct sr_node *)hash_lookup(OspfSR.neighbors,
- (void *)&rid);
+ if (argv_find(argv, argc, "self-originate", &idx)) {
+ srn = OspfSR.self;
+ show_vty_sr_node(vty, srn);
+ return CMD_SUCCESS;
+ }
+
+ if (argv_find(argv, argc, "A.B.C.D", &idx)) {
+ if (!inet_aton(argv[idx]->arg, &rid)) {
+ vty_out(vty,
+ "Specified Router ID %s is invalid\n",
+ argv[idx]->arg);
+ return CMD_WARNING_CONFIG_FAILED;
}
+ /* Get the SR Node from the SRDB */
+ srn = (struct sr_node *)hash_lookup(OspfSR.neighbors,
+ (void *)&rid);
show_vty_sr_node(vty, srn);
+ return CMD_SUCCESS;
}
+
+ /* No parameters have been provided, Iterate through all the SRDB */
+ hash_iterate(
+ OspfSR.neighbors,
+ (void (*)(struct hash_backet *, void *))show_srdb_entry,
+ (void *)vty);
return CMD_SUCCESS;
}
install_element(OSPF_NODE, &sr_prefix_sid_cmd);
install_element(OSPF_NODE, &no_sr_prefix_sid_cmd);
- return;
}
* Author: Olivier Dugeon <olivier.dugeon@orange.com>
* Author: Anselme Sawadogo <anselmesawadogo@gmail.com>
*
- * Copyright (C) 2016 - 2017 Orange Labs http://www.orange.com
+ * Copyright (C) 2016 - 2018 Orange Labs http://www.orange.com
*
- * This file is part of FRR.
+ * This program 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 of the License, or (at your option)
+ * any later version.
*
- * 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.
+ * This program 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.
*
- * 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.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _FRR_OSPF_SR_H
#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
+/* Label range for Adj-SID attribution purpose. Start just right after SRGB */
+#define ADJ_SID_MIN MPLS_DEFAULT_MAX_SRGB_LABEL
+#define ADJ_SID_MAX (MPLS_DEFAULT_MAX_SRGB_LABEL + 1000)
#define OSPF_SR_DEFAULT_METRIC 1
uint32_t instance;
/* Flags to manage this link parameters. */
- uint32_t flags[2];
+ uint8_t flags[2];
/* Segment Routing ID */
uint32_t sid[2];
uint32_t instance;
/* Flags to manage this prefix parameters. */
- uint32_t flags;
+ uint8_t flags;
/* Segment Routing ID */
uint32_t sid;
/* 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 */
+ /*
+ * 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;
};
/* 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 *);
+extern void ospf_sr_ext_link_lsa_update(struct ospf_lsa *lsa);
+extern void ospf_sr_ext_link_lsa_delete(struct ospf_lsa *lsa);
+extern void ospf_sr_ext_prefix_lsa_update(struct ospf_lsa *lsa);
+extern void ospf_sr_ext_prefix_lsa_delete(struct ospf_lsa *lsa);
/* Segment Routing configuration functions */
extern uint32_t get_ext_link_label_value(void);
-extern void ospf_sr_config_write_router(struct vty *);
+extern void ospf_sr_config_write_router(struct vty *vty);
+extern void ospf_sr_update_prefix(struct interface *ifp, struct prefix *p);
/* Segment Routing re-routing function */
-extern void ospf_sr_update_timer_add(struct ospf *);
+extern void ospf_sr_update_timer_add(struct ospf *ospf);
#endif /* _FRR_OSPF_SR_H */
if (!CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN))
instance = ospf->instance;
+ ospf_opaque_term();
+
ospf_delete(ospf);
if (ospf->name) {