3 * Copyright (C) 2018 Cumulus Networks, Inc.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "srcdest_table.h"
28 #include "static_vrf.h"
29 #include "static_routes.h"
30 #include "static_zebra.h"
31 #include "static_nht.h"
33 static void static_nht_update_path(struct static_path
*pn
, struct prefix
*nhp
,
34 uint32_t nh_num
, vrf_id_t nh_vrf_id
,
37 struct static_nexthop
*nh
;
39 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
40 if (nh
->nh_vrf_id
!= nh_vrf_id
)
43 if (nh
->type
!= STATIC_IPV4_GATEWAY
44 && nh
->type
!= STATIC_IPV4_GATEWAY_IFNAME
45 && nh
->type
!= STATIC_IPV6_GATEWAY
46 && nh
->type
!= STATIC_IPV6_GATEWAY_IFNAME
)
49 if (nhp
->family
== AF_INET
50 && nhp
->u
.prefix4
.s_addr
== nh
->addr
.ipv4
.s_addr
)
51 nh
->nh_valid
= !!nh_num
;
53 if (nhp
->family
== AF_INET6
54 && memcmp(&nhp
->u
.prefix6
, &nh
->addr
.ipv6
, IPV6_MAX_BYTELEN
)
56 nh
->nh_valid
= !!nh_num
;
58 if (nh
->state
== STATIC_START
)
59 static_zebra_route_add(pn
, true);
63 static void static_nht_update_safi(struct prefix
*sp
, struct prefix
*nhp
,
64 uint32_t nh_num
, afi_t afi
, safi_t safi
,
65 struct vrf
*vrf
, vrf_id_t nh_vrf_id
)
67 struct route_table
*stable
;
68 struct static_vrf
*svrf
;
69 struct route_node
*rn
;
70 struct static_path
*pn
;
71 struct static_route_info
*si
;
77 stable
= static_vrf_static_table(afi
, safi
, svrf
);
82 rn
= srcdest_rnode_lookup(stable
, sp
, NULL
);
84 si
= static_route_info_from_rnode(rn
);
85 frr_each(static_path_list
, &si
->path_list
, pn
) {
86 static_nht_update_path(pn
, nhp
, nh_num
,
89 route_unlock_node(rn
);
94 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
95 si
= static_route_info_from_rnode(rn
);
98 frr_each(static_path_list
, &si
->path_list
, pn
) {
99 static_nht_update_path(pn
, nhp
, nh_num
, nh_vrf_id
, vrf
);
104 void static_nht_update(struct prefix
*sp
, struct prefix
*nhp
, uint32_t nh_num
,
105 afi_t afi
, safi_t safi
, vrf_id_t nh_vrf_id
)
110 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
111 static_nht_update_safi(sp
, nhp
, nh_num
, afi
, safi
, vrf
,
115 static void static_nht_reset_start_safi(struct prefix
*nhp
, afi_t afi
,
116 safi_t safi
, struct vrf
*vrf
,
119 struct static_vrf
*svrf
;
120 struct route_table
*stable
;
121 struct static_nexthop
*nh
;
122 struct static_path
*pn
;
123 struct route_node
*rn
;
124 struct static_route_info
*si
;
130 stable
= static_vrf_static_table(afi
, safi
, svrf
);
134 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
135 si
= static_route_info_from_rnode(rn
);
138 frr_each(static_path_list
, &si
->path_list
, pn
) {
139 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
140 if (nh
->nh_vrf_id
!= nh_vrf_id
)
143 if (nhp
->family
== AF_INET
144 && nhp
->u
.prefix4
.s_addr
145 != nh
->addr
.ipv4
.s_addr
)
148 if (nhp
->family
== AF_INET6
149 && memcmp(&nhp
->u
.prefix6
, &nh
->addr
.ipv6
,
155 * We've been told that a nexthop we
156 * depend on has changed in some manner,
157 * so reset the state machine to allow
160 nh
->state
= STATIC_START
;
166 void static_nht_reset_start(struct prefix
*nhp
, afi_t afi
, safi_t safi
,
171 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
172 static_nht_reset_start_safi(nhp
, afi
, safi
, vrf
, nh_vrf_id
);
175 static void static_nht_mark_state_safi(struct prefix
*sp
, afi_t afi
,
176 safi_t safi
, struct vrf
*vrf
,
177 enum static_install_states state
)
179 struct static_vrf
*svrf
;
180 struct route_table
*stable
;
181 struct route_node
*rn
;
182 struct static_nexthop
*nh
;
183 struct static_path
*pn
;
184 struct static_route_info
*si
;
190 stable
= static_vrf_static_table(afi
, safi
, svrf
);
194 rn
= srcdest_rnode_lookup(stable
, sp
, NULL
);
199 frr_each(static_path_list
, &si
->path_list
, pn
) {
200 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
206 route_unlock_node(rn
);
209 void static_nht_mark_state(struct prefix
*sp
, safi_t safi
, vrf_id_t vrf_id
,
210 enum static_install_states state
)
216 if (sp
->family
== AF_INET6
)
219 vrf
= vrf_lookup_by_id(vrf_id
);
220 if (!vrf
|| !vrf
->info
)
223 static_nht_mark_state_safi(sp
, afi
, safi
, vrf
, state
);