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_rn(struct route_node
*rn
,
34 struct prefix
*nhp
, uint32_t nh_num
,
35 vrf_id_t nh_vrf_id
, struct vrf
*vrf
,
38 struct static_route
*si
;
40 for (si
= rn
->info
; si
; si
= si
->next
) {
41 if (si
->nh_vrf_id
!= nh_vrf_id
)
44 if (si
->type
!= STATIC_IPV4_GATEWAY
45 && si
->type
!= STATIC_IPV4_GATEWAY_IFNAME
46 && si
->type
!= STATIC_IPV6_GATEWAY
47 && si
->type
!= STATIC_IPV6_GATEWAY_IFNAME
)
50 if (nhp
->family
== AF_INET
51 && nhp
->u
.prefix4
.s_addr
== si
->addr
.ipv4
.s_addr
)
52 si
->nh_valid
= !!nh_num
;
54 if (nhp
->family
== AF_INET6
55 && memcmp(&nhp
->u
.prefix6
, &si
->addr
.ipv6
, 16) == 0)
56 si
->nh_valid
= !!nh_num
;
58 if (si
->state
== STATIC_START
)
59 static_zebra_route_add(rn
, si
, vrf
->vrf_id
, 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
;
75 stable
= static_vrf_static_table(afi
, safi
, svrf
);
80 rn
= srcdest_rnode_lookup(stable
, sp
, NULL
);
82 static_nht_update_rn(rn
, nhp
, nh_num
, nh_vrf_id
,
84 route_unlock_node(rn
);
89 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
))
90 static_nht_update_rn(rn
, nhp
, nh_num
, nh_vrf_id
, vrf
, safi
);
94 void static_nht_update(struct prefix
*sp
, struct prefix
*nhp
,
95 uint32_t nh_num
, afi_t afi
, vrf_id_t nh_vrf_id
)
100 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
101 static_nht_update_safi(sp
, nhp
, nh_num
, afi
, SAFI_UNICAST
,
103 static_nht_update_safi(sp
, nhp
, nh_num
, afi
, SAFI_MULTICAST
,
108 static void static_nht_reset_start_safi(struct prefix
*nhp
, afi_t afi
,
109 safi_t safi
, struct vrf
*vrf
,
112 struct static_vrf
*svrf
;
113 struct route_table
*stable
;
114 struct static_route
*si
;
115 struct route_node
*rn
;
121 stable
= static_vrf_static_table(afi
, safi
, svrf
);
125 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
126 for (si
= rn
->info
; si
; si
= si
->next
) {
127 if (si
->nh_vrf_id
!= nh_vrf_id
)
130 if (nhp
->family
== AF_INET
131 && nhp
->u
.prefix4
.s_addr
!= si
->addr
.ipv4
.s_addr
)
134 if (nhp
->family
== AF_INET6
135 && memcmp(&nhp
->u
.prefix6
, &si
->addr
.ipv6
, 16) != 0)
139 * We've been told that a nexthop we depend
140 * on has changed in some manner, so reset
141 * the state machine to allow us to start
144 si
->state
= STATIC_START
;
149 void static_nht_reset_start(struct prefix
*nhp
, afi_t afi
, vrf_id_t nh_vrf_id
)
153 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
154 static_nht_reset_start_safi(nhp
, afi
, SAFI_UNICAST
,
156 static_nht_reset_start_safi(nhp
, afi
, SAFI_MULTICAST
,
161 static void static_nht_mark_state_safi(struct prefix
*sp
, afi_t afi
,
162 safi_t safi
, struct vrf
*vrf
,
163 enum static_install_states state
)
165 struct static_vrf
*svrf
;
166 struct route_table
*stable
;
167 struct static_route
*si
;
168 struct route_node
*rn
;
174 stable
= static_vrf_static_table(afi
, safi
, svrf
);
178 rn
= srcdest_rnode_lookup(stable
, sp
, NULL
);
182 for (si
= rn
->info
; si
; si
= si
->next
)
185 route_unlock_node(rn
);
188 void static_nht_mark_state(struct prefix
*sp
, vrf_id_t vrf_id
,
189 enum static_install_states state
)
195 if (sp
->family
== AF_INET6
)
198 vrf
= vrf_lookup_by_id(vrf_id
);
199 if (!vrf
|| !vrf
->info
)
202 static_nht_mark_state_safi(sp
, afi
, SAFI_UNICAST
, vrf
, state
);
203 static_nht_mark_state_safi(sp
, afi
, SAFI_MULTICAST
, vrf
, state
);