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 route_node
*rn
,
34 struct static_path
*pn
, struct prefix
*nhp
,
35 uint32_t nh_num
, vrf_id_t nh_vrf_id
,
36 struct vrf
*vrf
, safi_t safi
)
38 struct static_nexthop
*nh
;
40 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
41 if (nh
->nh_vrf_id
!= nh_vrf_id
)
44 if (nh
->type
!= STATIC_IPV4_GATEWAY
45 && nh
->type
!= STATIC_IPV4_GATEWAY_IFNAME
46 && nh
->type
!= STATIC_IPV6_GATEWAY
47 && nh
->type
!= STATIC_IPV6_GATEWAY_IFNAME
)
50 if (nhp
->family
== AF_INET
51 && nhp
->u
.prefix4
.s_addr
== nh
->addr
.ipv4
.s_addr
)
52 nh
->nh_valid
= !!nh_num
;
54 if (nhp
->family
== AF_INET6
55 && memcmp(&nhp
->u
.prefix6
, &nh
->addr
.ipv6
, 16) == 0)
56 nh
->nh_valid
= !!nh_num
;
58 if (nh
->state
== STATIC_START
)
59 static_zebra_route_add(rn
, pn
, safi
, 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(rn
, pn
, nhp
, nh_num
,
87 nh_vrf_id
, vrf
, safi
);
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(rn
, pn
, nhp
, nh_num
, nh_vrf_id
,
105 void static_nht_update(struct prefix
*sp
, struct prefix
*nhp
,
106 uint32_t nh_num
, afi_t afi
, vrf_id_t nh_vrf_id
)
111 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
112 static_nht_update_safi(sp
, nhp
, nh_num
, afi
, SAFI_UNICAST
,
114 static_nht_update_safi(sp
, nhp
, nh_num
, afi
, SAFI_MULTICAST
,
119 static void static_nht_reset_start_safi(struct prefix
*nhp
, afi_t afi
,
120 safi_t safi
, struct vrf
*vrf
,
123 struct static_vrf
*svrf
;
124 struct route_table
*stable
;
125 struct static_nexthop
*nh
;
126 struct static_path
*pn
;
127 struct route_node
*rn
;
128 struct static_route_info
*si
;
134 stable
= static_vrf_static_table(afi
, safi
, svrf
);
138 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
139 si
= static_route_info_from_rnode(rn
);
142 frr_each(static_path_list
, &si
->path_list
, pn
) {
143 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
144 if (nh
->nh_vrf_id
!= nh_vrf_id
)
147 if (nhp
->family
== AF_INET
148 && nhp
->u
.prefix4
.s_addr
149 != nh
->addr
.ipv4
.s_addr
)
152 if (nhp
->family
== AF_INET6
153 && memcmp(&nhp
->u
.prefix6
, &nh
->addr
.ipv6
,
159 * We've been told that a nexthop we
160 * depend on has changed in some manner,
161 * so reset the state machine to allow
164 nh
->state
= STATIC_START
;
170 void static_nht_reset_start(struct prefix
*nhp
, afi_t afi
, vrf_id_t nh_vrf_id
)
174 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
175 static_nht_reset_start_safi(nhp
, afi
, SAFI_UNICAST
,
177 static_nht_reset_start_safi(nhp
, afi
, SAFI_MULTICAST
,
182 static void static_nht_mark_state_safi(struct prefix
*sp
, afi_t afi
,
183 safi_t safi
, struct vrf
*vrf
,
184 enum static_install_states state
)
186 struct static_vrf
*svrf
;
187 struct route_table
*stable
;
188 struct route_node
*rn
;
189 struct static_nexthop
*nh
;
190 struct static_path
*pn
;
191 struct static_route_info
*si
;
197 stable
= static_vrf_static_table(afi
, safi
, svrf
);
201 rn
= srcdest_rnode_lookup(stable
, sp
, NULL
);
206 frr_each(static_path_list
, &si
->path_list
, pn
) {
207 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
213 route_unlock_node(rn
);
216 void static_nht_mark_state(struct prefix
*sp
, vrf_id_t vrf_id
,
217 enum static_install_states state
)
223 if (sp
->family
== AF_INET6
)
226 vrf
= vrf_lookup_by_id(vrf_id
);
227 if (!vrf
|| !vrf
->info
)
230 static_nht_mark_state_safi(sp
, afi
, SAFI_UNICAST
, vrf
, state
);
231 static_nht_mark_state_safi(sp
, afi
, SAFI_MULTICAST
, vrf
, state
);