diff options
author | Olivier Dugeon <olivier.dugeon@orange.com> | 2018-01-29 17:58:53 +0100 |
---|---|---|
committer | Olivier Dugeon <olivier.dugeon@orange.com> | 2018-01-29 17:58:53 +0100 |
commit | 7743f2f8c00ed2541454a806c1dc55257e06c7a5 (patch) | |
tree | 535706c0cba106a9579ed990156be19934c97f3d | |
parent | OSPFD: Set Segment Routing patch conform to C99 (diff) | |
download | frr-7743f2f8c00ed2541454a806c1dc55257e06c7a5.tar.xz frr-7743f2f8c00ed2541454a806c1dc55257e06c7a5.zip |
OSPFd: Update Segment Routing PR following review
Following various review, following files have been modfied:
- All: Change u_intXX_t typedef to standard uintXX_t types
- doc/OSPF-SR.rst: Update doc in particular the Linux Kernel configuration
section
- doc/ospfd.texi: Update CLI
- ospfd/ospf_dump.[c,h]: Add new 'debug ospf sr' when performing 'sh run'
- ospfd/ospf_ext.[c, h]: Various bug corrections notably to handle flooding of
Extended Prefix at startup. iFix TLVs size for LAN Adjacency.
Update Licence as per Community.md
- ospfd/ospf_opaque.c: Add proper termination function call to remove MPLS entries
- ospfd/ospf_ri.[c,h]: Bug corrections
- ospfd/ospf_sr.[c,h]: Various bug corrections, notably to determine the nexthop
SR Node. Add support to 'no-php-flag'.
Update Licence as per Community.md
- ospfd/ospfd.c: Add call to 'ospf_opaque_term()'
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
-rw-r--r-- | doc/OSPF-SR.rst | 249 | ||||
-rw-r--r-- | doc/ospfd.texi | 10 | ||||
-rw-r--r-- | ospfd/ospf_dump.c | 12 | ||||
-rw-r--r-- | ospfd/ospf_dump.h | 10 | ||||
-rw-r--r-- | ospfd/ospf_ext.c | 579 | ||||
-rw-r--r-- | ospfd/ospf_ext.h | 53 | ||||
-rw-r--r-- | ospfd/ospf_opaque.c | 1 | ||||
-rw-r--r-- | ospfd/ospf_ri.c | 42 | ||||
-rw-r--r-- | ospfd/ospf_ri.h | 5 | ||||
-rw-r--r-- | ospfd/ospf_sr.c | 739 | ||||
-rw-r--r-- | ospfd/ospf_sr.h | 56 | ||||
-rw-r--r-- | ospfd/ospfd.c | 2 |
12 files changed, 976 insertions, 782 deletions
diff --git a/doc/OSPF-SR.rst b/doc/OSPF-SR.rst index 4aa9f4f5e..0ee1a12f2 100644 --- a/doc/OSPF-SR.rst +++ b/doc/OSPF-SR.rst @@ -1,56 +1,61 @@ 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. :: @@ -85,69 +90,177 @@ The figure below shows the relation between the various files: | | +---------------+ - 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 diff --git a/doc/ospfd.texi b/doc/ospfd.texi index c013412b9..9feba08b2 100644 --- a/doc/ospfd.texi +++ b/doc/ospfd.texi @@ -729,7 +729,7 @@ Show Router Capabilities PCE parameters. @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} {} @@ -746,15 +746,17 @@ label in the MPLS FIB. @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} {} diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index a16722076..66ab59b81 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -1788,6 +1788,18 @@ static int config_write_debug(struct vty *vty) 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; } diff --git a/ospfd/ospf_dump.h b/ospfd/ospf_dump.h index 6ec92767d..99d7512f1 100644 --- a/ospfd/ospf_dump.h +++ b/ospfd/ospf_dump.h @@ -94,15 +94,15 @@ /* 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) diff --git a/ospfd/ospf_ext.c b/ospfd/ospf_ext.c index f56bca6b7..c46de4d05 100644 --- a/ospfd/ospf_ext.c +++ b/ospfd/ospf_ext.c @@ -4,27 +4,24 @@ * * 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> @@ -74,13 +71,15 @@ */ 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); @@ -120,11 +119,11 @@ int ospf_ext_init(void) 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. */ @@ -137,16 +136,17 @@ int ospf_ext_init(void) 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. */ @@ -157,7 +157,8 @@ int ospf_ext_init(void) 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; } @@ -167,41 +168,30 @@ int ospf_ext_init(void) /* * 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 */ @@ -254,15 +244,15 @@ static struct ext_itf *lookup_ext_by_instance(struct ospf_lsa *lsa) 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, @@ -295,27 +285,20 @@ static void set_ext_link(struct ext_itf *exti, uint8_t type, struct in_addr id, /* 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); @@ -332,7 +315,6 @@ static void set_prefix_sid(struct ext_itf *exti, uint8_t algorithm, exti->node_sid.value = htonl(value); } - return; } /* Adjacency SID SubTLV - section 6.1 */ @@ -373,7 +355,7 @@ static void set_adj_sid(struct ext_itf *exti, bool backup, uint32_t value, 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 */ @@ -414,7 +396,7 @@ static void set_lan_adj_sid(struct ext_itf *exti, bool backup, uint32_t value, 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 */ @@ -424,7 +406,7 @@ static void set_rmt_itf_addr(struct ext_itf *exti, struct in_addr rmtif) 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; + } /* @@ -438,7 +420,7 @@ static void set_rmt_itf_addr(struct ext_itf *exti, struct in_addr rmtif) * @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; @@ -451,16 +433,15 @@ int ospf_ext_schedule_prefix_index(struct interface *ifp, uint32_t index, 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); @@ -471,9 +452,8 @@ int ospf_ext_schedule_prefix_index(struct interface *ifp, uint32_t index, } 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); @@ -499,9 +479,8 @@ void ospf_ext_update_sr(bool enable) 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; @@ -521,9 +500,11 @@ void ospf_ext_update_sr(bool enable) 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) @@ -533,16 +514,16 @@ 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; } @@ -562,93 +543,87 @@ static int ospf_ext_link_del_if(struct interface *ifp) 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); } /* @@ -666,19 +641,18 @@ static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status) 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; } @@ -751,6 +725,12 @@ static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status) 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) { @@ -760,7 +740,6 @@ static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status) ospf_ext_link_lsa_schedule(exti, REORIGINATE_THIS_LSA); } - return; } /* Callbacks to handle Extended Link Segment Routing LSA information */ @@ -768,9 +747,7 @@ static int ospf_ext_link_lsa_update(struct ospf_lsa *lsa) { /* 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; } @@ -798,12 +775,14 @@ static int ospf_ext_pref_lsa_update(struct ospf_lsa *lsa) /* 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) @@ -822,15 +801,17 @@ static int ospf_ext_pref_lsa_update(struct ospf_lsa *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) @@ -840,7 +821,7 @@ 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 */ @@ -853,7 +834,8 @@ static void ospf_ext_pref_lsa_body_set(struct stream *s, struct ext_itf *exti) /* 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); @@ -861,12 +843,12 @@ static void ospf_ext_pref_lsa_body_set(struct stream *s, struct ext_itf *exti) /* 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) @@ -875,10 +857,13 @@ static void ospf_ext_link_lsa_body_set(struct stream *s, struct ext_itf *exti) 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); @@ -886,13 +871,15 @@ static void ospf_ext_link_lsa_body_set(struct stream *s, struct ext_itf *exti) /* 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); @@ -902,7 +889,6 @@ static void ospf_ext_link_lsa_body_set(struct stream *s, struct ext_itf *exti) build_tlv(s, &exti->lan_sid[0].header); } - return; } /* Create new Extended Prefix opaque-LSA for every extended prefix */ @@ -912,6 +898,7 @@ static struct ospf_lsa *ospf_ext_pref_lsa_new(struct ospf_area *area, 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; @@ -923,8 +910,9 @@ static struct ospf_lsa *ospf_ext_pref_lsa_new(struct ospf_area *area, 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; } @@ -933,8 +921,10 @@ static struct ospf_lsa *ospf_ext_pref_lsa_new(struct ospf_area *area, 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); @@ -943,8 +933,8 @@ static struct ospf_lsa *ospf_ext_pref_lsa_new(struct ospf_area *area, /* 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); @@ -956,9 +946,9 @@ static struct ospf_lsa *ospf_ext_pref_lsa_new(struct ospf_area *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. */ @@ -969,19 +959,23 @@ static struct ospf_lsa *ospf_ext_pref_lsa_new(struct ospf_area *area, 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); @@ -1007,8 +1001,9 @@ static struct ospf_lsa *ospf_ext_link_lsa_new(struct ospf_area *area, 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); @@ -1019,16 +1014,18 @@ static struct ospf_lsa *ospf_ext_link_lsa_new(struct ospf_area *area, /* 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); @@ -1041,19 +1038,23 @@ static struct ospf_lsa *ospf_ext_link_lsa_new(struct ospf_area *area, 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); @@ -1062,8 +1063,10 @@ static struct ospf_lsa *ospf_ext_link_lsa_new(struct ospf_area *area, 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) { @@ -1072,20 +1075,22 @@ static int ospf_ext_pref_lsa_originate1(struct ospf_area *area, /* 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. */ @@ -1096,12 +1101,13 @@ static int ospf_ext_pref_lsa_originate1(struct ospf_area *area, 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); } @@ -1110,8 +1116,10 @@ static int ospf_ext_pref_lsa_originate1(struct ospf_area *area, 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) { @@ -1119,14 +1127,15 @@ static int ospf_ext_link_lsa_originate1(struct ospf_area *area, 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; } @@ -1142,12 +1151,13 @@ static int ospf_ext_link_lsa_originate1(struct ospf_area *area, 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); } @@ -1166,16 +1176,15 @@ static int ospf_ext_pref_lsa_originate(void *arg) 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)) { @@ -1192,7 +1201,9 @@ static int ospf_ext_pref_lsa_originate(void *arg) 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, @@ -1204,9 +1215,9 @@ static int ospf_ext_pref_lsa_originate(void *arg) /* 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); } @@ -1225,8 +1236,8 @@ static int ospf_ext_link_lsa_originate(void *arg) 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; } @@ -1246,7 +1257,9 @@ static int ospf_ext_link_lsa_originate(void *arg) 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, @@ -1258,9 +1271,9 @@ static int ospf_ext_link_lsa_originate(void *arg) /* 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); @@ -1284,21 +1297,25 @@ static struct ospf_lsa *ospf_ext_pref_lsa_refresh(struct ospf_lsa *lsa) * 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); } @@ -1316,22 +1333,24 @@ static struct ospf_lsa *ospf_ext_pref_lsa_refresh(struct ospf_lsa *lsa) 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; } @@ -1341,8 +1360,9 @@ static struct ospf_lsa *ospf_ext_pref_lsa_refresh(struct ospf_lsa *lsa) /* 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); } @@ -1363,17 +1383,16 @@ static struct ospf_lsa *ospf_ext_link_lsa_refresh(struct ospf_lsa *lsa) * 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); } @@ -1381,12 +1400,12 @@ static struct ospf_lsa *ospf_ext_link_lsa_refresh(struct ospf_lsa *lsa) /* 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); @@ -1394,21 +1413,18 @@ static struct ospf_lsa *ospf_ext_link_lsa_refresh(struct ospf_lsa *lsa) 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; } @@ -1419,9 +1435,8 @@ static struct ospf_lsa *ospf_ext_link_lsa_refresh(struct ospf_lsa *lsa) /* 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); } @@ -1449,8 +1464,7 @@ static void ospf_ext_pref_lsa_schedule(struct ext_itf *exti, 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" : "", @@ -1459,8 +1473,8 @@ static void ospf_ext_pref_lsa_schedule(struct ext_itf *exti, /* 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( @@ -1488,11 +1502,10 @@ static void ospf_ext_pref_lsa_schedule(struct ext_itf *exti, 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 */ @@ -1516,8 +1529,7 @@ static void ospf_ext_link_lsa_schedule(struct ext_itf *exti, 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" : "", @@ -1526,8 +1538,8 @@ static void ospf_ext_link_lsa_schedule(struct ext_itf *exti, /* 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( @@ -1555,11 +1567,10 @@ static void ospf_ext_link_lsa_schedule(struct ext_itf *exti, 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 */ @@ -1572,18 +1583,22 @@ static void ospf_ext_lsa_schedule(struct ext_itf *exti, enum lsa_opcode op) 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)); @@ -1597,8 +1612,8 @@ static uint16_t show_vty_ext_link_adj_sid(struct vty *vty, 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", @@ -1617,9 +1632,9 @@ static uint16_t show_vty_ext_link_lan_adj_sid(struct vty *vty, (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", @@ -1647,7 +1662,7 @@ static uint16_t show_vty_link_info(struct vty *vty, struct tlv_header *ext) 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)); @@ -1697,7 +1712,6 @@ static void ospf_ext_link_show_info(struct vty *vty, struct ospf_lsa *lsa) } } - return; } /* Prefix SID SubTLV */ @@ -1708,8 +1722,8 @@ static uint16_t show_vty_ext_pref_pref_sid(struct vty *vty, (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" @@ -1730,8 +1744,8 @@ static uint16_t show_vty_pref_info(struct vty *vty, struct tlv_header *ext) 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); @@ -1773,5 +1787,4 @@ static void ospf_ext_pref_show_info(struct vty *vty, struct ospf_lsa *lsa) } } - return; } diff --git a/ospfd/ospf_ext.h b/ospfd/ospf_ext.h index 318a9821f..130faf671 100644 --- a/ospfd/ospf_ext.h +++ b/ospfd/ospf_ext.h @@ -4,27 +4,24 @@ * * 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_ @@ -42,7 +39,7 @@ * * * 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 * @@ -71,7 +68,7 @@ /* 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 */ @@ -94,8 +91,10 @@ #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 */ @@ -146,8 +145,10 @@ struct ospf_ext_lp { /* 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 */ @@ -190,7 +191,9 @@ struct ext_itf { /* 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_ */ diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 292d5e818..78d82f8a6 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -93,7 +93,6 @@ void ospf_opaque_init(void) if (ospf_router_info_init() != 0) exit(1); - /* Force Extended Prefix/Link to Type 10 */ if (ospf_ext_init() != 0) exit(1); diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c index db68ec9de..d8fa4c72f 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -69,7 +69,10 @@ struct ospf_pce_info { struct ri_pce_subtlv_cap_flag pce_cap_flag; }; -/* Store Router Information Segment Routing TLV and SubTLV in network byte order. */ +/* + * Store Router Information Segment Routing TLV and SubTLV + * in network byte order + */ struct ospf_ri_sr_info { bool enabled; /* Algorithms supported by the node */ @@ -195,23 +198,6 @@ static int ospf_router_info_register(u_int8_t scope) 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) { @@ -220,8 +206,6 @@ void ospf_router_info_term(void) OspfRI.enabled = false; - ospf_router_info_unregister(); - return; } @@ -235,6 +219,7 @@ static void del_pce_info(void *val) 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; @@ -454,7 +439,6 @@ static void set_sr_algorithm(uint8_t algo) 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 */ @@ -468,7 +452,6 @@ static void unset_sr_algorithm(uint8_t algo) 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 */ @@ -485,11 +468,10 @@ static void set_sr_sid_label_range(struct sr_srgb srgb) 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); @@ -497,7 +479,6 @@ static void unset_sr_sid_label_range() 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 */ @@ -507,16 +488,14 @@ static void set_sr_node_msd(uint8_t msd) 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) @@ -1041,7 +1020,7 @@ static int ospf_router_info_lsa_update(struct ospf_lsa *lsa) /* Sanity Check */ if (lsa == NULL) { - zlog_warn("OSPF-RI (ospf_router_info_lsa_update): Abort! LSA is NULL"); + zlog_warn("OSPF-RI (%s): Abort! LSA is NULL", __func__); return -1; } @@ -1050,8 +1029,8 @@ static int ospf_router_info_lsa_update(struct ospf_lsa *lsa) 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 */ @@ -1239,6 +1218,7 @@ static uint16_t show_vty_sr_algorithm(struct vty *vty, struct tlv_header *tlvh) struct ri_sr_tlv_sr_algorithm *algo = (struct ri_sr_tlv_sr_algorithm *)tlvh; int i; + if (vty != NULL) { vty_out(vty, " Segment Routing Algorithm TLV:\n"); for (i = 0; i < ntohs(algo->header.length); i++) { diff --git a/ospfd/ospf_ri.h b/ospfd/ospf_ri.h index 7f3a5a222..07583f0b7 100644 --- a/ospfd/ospf_ri.h +++ b/ospfd/ospf_ri.h @@ -87,7 +87,7 @@ struct ri_tlv_router_cap { #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 @@ -177,6 +177,7 @@ struct scope_info { 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 */ diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c index eae488f77..3397ed7c0 100644 --- a/ospfd/ospf_sr.c +++ b/ospfd/ospf_sr.c @@ -1,30 +1,27 @@ /* * 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> @@ -87,7 +84,7 @@ static unsigned int sr_hash(void *p) { 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 */ @@ -96,7 +93,7 @@ static int sr_cmp(const void *p1, const void *p2) 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 */ @@ -107,7 +104,7 @@ static void del_sr_link(void *val) 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 */ @@ -117,7 +114,7 @@ static void del_sr_pref(void *val) del_sid_nhlfe(srp->nhlfe); XFREE(MTYPE_OSPF_SR_PARAMS, val); - return; + } /* Allocate new Segment Routine node */ @@ -134,9 +131,7 @@ static struct sr_node *sr_node_new(struct in_addr *rid) /* 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; } @@ -197,6 +192,7 @@ static struct sr_node *get_sr_node_by_nexthop(struct ospf *ospf, struct listnode *node; struct route_node *rn; struct sr_node *srn; + bool found; /* Sanity check */ if (OspfSR.neighbors == NULL) @@ -207,12 +203,20 @@ static struct sr_node *get_sr_node_by_nexthop(struct ospf *ospf, 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) @@ -237,7 +241,7 @@ static int ospf_sr_start(struct ospf *ospf) 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), @@ -255,7 +259,7 @@ static int ospf_sr_start(struct ospf *ospf) 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)) { @@ -285,55 +289,17 @@ static int ospf_sr_start(struct ospf *ospf) 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); } @@ -348,7 +314,7 @@ int ospf_sr_init(void) { 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; @@ -363,7 +329,7 @@ int ospf_sr_init(void) 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"); @@ -437,15 +403,16 @@ static struct ospf_neighbor *get_neighbor_by_addr(struct ospf *top, 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; } @@ -453,7 +420,7 @@ static struct ospf_neighbor *get_neighbor_by_addr(struct ospf *top, 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; @@ -463,19 +430,21 @@ static struct ospf_path *get_nexthop_by_addr(struct ospf *top, 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 */ @@ -494,7 +463,7 @@ static int compute_link_nhlfe(struct sr_link *srl) 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); @@ -551,7 +520,7 @@ static int compute_prefix_nhlfe(struct sr_prefix *srp) 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); @@ -574,9 +543,16 @@ static int compute_prefix_nhlfe(struct sr_prefix *srp) 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; @@ -593,7 +569,7 @@ static int compute_prefix_nhlfe(struct sr_prefix *srp) 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)); @@ -603,8 +579,10 @@ static int compute_prefix_nhlfe(struct sr_prefix *srp) /* 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; @@ -614,7 +592,7 @@ static int compute_prefix_nhlfe(struct sr_prefix *srp) 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; @@ -646,13 +624,13 @@ static int ospf_zebra_send_mpls_labels(int cmd, struct sr_nhlfe nhlfe) 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 */ @@ -689,12 +667,12 @@ static int ospf_zebra_send_mpls_ftn(int cmd, struct sr_nhlfe nhlfe) } 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 */ @@ -806,10 +784,10 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh) 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); } @@ -843,8 +821,8 @@ static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh) 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; } @@ -867,7 +845,7 @@ static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh) } 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; @@ -926,7 +904,7 @@ static void update_ext_link_sid(struct sr_node *srn, struct sr_link *srl, } 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)); @@ -955,11 +933,16 @@ static void update_ext_link_sid(struct sr_node *srn, struct sr_link *srl, &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); } } @@ -978,7 +961,7 @@ static void update_ext_prefix_sid(struct sr_node *srn, struct sr_prefix *srp) 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)) @@ -992,7 +975,7 @@ static void update_ext_prefix_sid(struct sr_node *srn, struct sr_prefix *srp) } 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)); @@ -1004,9 +987,8 @@ static void update_ext_prefix_sid(struct sr_node *srn, struct sr_prefix *srp) 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) { @@ -1020,12 +1002,14 @@ static void update_ext_prefix_sid(struct sr_node *srn, struct sr_prefix *srp) 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); } } @@ -1042,16 +1026,18 @@ static void update_in_nhlfe(struct hash_backet *backet, void *args) 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 */ @@ -1105,8 +1091,9 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa) 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)); @@ -1115,9 +1102,7 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa) 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; } @@ -1128,15 +1113,16 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa) /* 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; @@ -1154,6 +1140,7 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa) 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++) @@ -1181,8 +1168,8 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa) 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; @@ -1210,7 +1197,6 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa) (void *)srn); } - return; } /* @@ -1224,16 +1210,13 @@ void ospf_sr_ri_lsa_delete(struct ospf_lsa *lsa) 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; } @@ -1243,17 +1226,15 @@ void ospf_sr_ri_lsa_delete(struct ospf_lsa *lsa) /* 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; } @@ -1261,7 +1242,6 @@ void ospf_sr_ri_lsa_delete(struct ospf_lsa *lsa) /* Remove SR node */ sr_node_del(srn); - return; } /* Update Segment Routing from Extended Link LSA */ @@ -1276,16 +1256,13 @@ void ospf_sr_ext_link_lsa_update(struct ospf_lsa *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; } @@ -1297,8 +1274,8 @@ void ospf_sr_ext_link_lsa_update(struct ospf_lsa *lsa) /* 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; } @@ -1331,16 +1308,13 @@ void ospf_sr_ext_link_lsa_delete(struct ospf_lsa *lsa) 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; } @@ -1348,13 +1322,14 @@ void ospf_sr_ext_link_lsa_delete(struct ospf_lsa *lsa) 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; } @@ -1371,13 +1346,12 @@ void ospf_sr_ext_link_lsa_delete(struct ospf_lsa *lsa) 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 */ @@ -1392,16 +1366,14 @@ void ospf_sr_ext_prefix_lsa_update(struct ospf_lsa *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; } @@ -1413,8 +1385,8 @@ void ospf_sr_ext_prefix_lsa_update(struct ospf_lsa *lsa) /* 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; } @@ -1447,16 +1419,13 @@ void ospf_sr_ext_prefix_lsa_delete(struct ospf_lsa *lsa) 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; } @@ -1464,13 +1433,14 @@ void ospf_sr_ext_prefix_lsa_delete(struct ospf_lsa *lsa) 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; } @@ -1486,13 +1456,12 @@ void ospf_sr_ext_prefix_lsa_delete(struct ospf_lsa *lsa) 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 */ @@ -1508,6 +1477,61 @@ uint32_t get_ext_link_label_value(void) } /* + * 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 */ @@ -1518,8 +1542,6 @@ static void ospf_sr_nhlfe_update(struct hash_backet *backet, void *args) struct listnode *node; struct sr_prefix *srp; struct sr_nhlfe old; - struct interface *ifp; - struct prefix p; int rc; /* Sanity Check */ @@ -1530,40 +1552,9 @@ static void ospf_sr_nhlfe_update(struct hash_backet *backet, void *args) 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)) { @@ -1608,7 +1599,7 @@ static int ospf_sr_update_schedule(struct thread *t) 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, @@ -1617,8 +1608,8 @@ static int ospf_sr_update_schedule(struct thread *t) 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)); @@ -1644,9 +1635,11 @@ void ospf_sr_update_timer_add(struct ospf *ospf) OSPF_SR_UPDATE_INTERVAL, &ospf->t_sr_update); } -/*------------------------------------------------------------------------* +/* + * -------------------------------------- * Followings are vty command functions. - *------------------------------------------------------------------------*/ + * -------------------------------------- + */ /* * Segment Routing Router configuration @@ -1667,22 +1660,28 @@ void ospf_sr_config_write_router(struct vty *vty) 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" : ""); } } } @@ -1786,42 +1785,42 @@ DEFUN (sr_sid_label_range, 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); @@ -1836,10 +1835,12 @@ DEFUN (sr_sid_label_range, 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)) @@ -1848,6 +1849,10 @@ DEFUN (no_sr_sid_label_range, /* 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); @@ -1868,25 +1873,28 @@ DEFUN (sr_node_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); @@ -1896,10 +1904,11 @@ DEFUN (sr_node_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)) @@ -1907,6 +1916,8 @@ DEFUN (no_sr_node_msd, /* 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); @@ -1916,31 +1927,39 @@ DEFUN (no_sr_node_msd, 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; } @@ -1948,97 +1967,147 @@ DEFUN (sr_prefix_sid, /* 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) { @@ -2047,7 +2116,7 @@ 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 */ @@ -2055,7 +2124,7 @@ static void show_vty_sr_node(struct vty *vty, struct sr_node *srn) 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"); @@ -2066,23 +2135,23 @@ static void show_vty_sr_node(struct vty *vty, struct sr_node *srn) 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)); @@ -2090,22 +2159,22 @@ static void show_vty_sr_node(struct vty *vty, struct sr_node *srn) 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)); @@ -2133,7 +2202,7 @@ DEFUN (show_ip_opsf_srdb, "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; @@ -2145,30 +2214,31 @@ DEFUN (show_ip_opsf_srdb, 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; } @@ -2186,5 +2256,4 @@ void ospf_sr_register_vty(void) install_element(OSPF_NODE, &sr_prefix_sid_cmd); install_element(OSPF_NODE, &no_sr_prefix_sid_cmd); - return; } diff --git a/ospfd/ospf_sr.h b/ospfd/ospf_sr.h index 938e4740c..172e8a536 100644 --- a/ospfd/ospf_sr.h +++ b/ospfd/ospf_sr.h @@ -7,24 +7,21 @@ * 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 @@ -43,9 +40,9 @@ #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 @@ -259,7 +256,7 @@ struct sr_link { uint32_t instance; /* Flags to manage this link parameters. */ - uint32_t flags[2]; + uint8_t flags[2]; /* Segment Routing ID */ uint32_t sid[2]; @@ -279,7 +276,7 @@ struct sr_prefix { uint32_t instance; /* Flags to manage this prefix parameters. */ - uint32_t flags; + uint8_t flags; /* Segment Routing ID */ uint32_t sid; @@ -291,8 +288,10 @@ struct sr_prefix { /* 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; }; @@ -303,13 +302,14 @@ extern void ospf_sr_term(void); /* Segment Routing LSA update & delete functions */ extern void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa); extern void ospf_sr_ri_lsa_delete(struct ospf_lsa *lsa); -extern void ospf_sr_ext_link_lsa_update(struct ospf_lsa *); -extern void ospf_sr_ext_link_lsa_delete(struct ospf_lsa *); -extern void ospf_sr_ext_prefix_lsa_update(struct ospf_lsa *); -extern void ospf_sr_ext_prefix_lsa_delete(struct ospf_lsa *); +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 */ diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 192619743..b60cdb352 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -766,6 +766,8 @@ static void ospf_finish_final(struct ospf *ospf) if (!CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN)) instance = ospf->instance; + ospf_opaque_term(); + ospf_delete(ospf); if (ospf->name) { |