]> git.proxmox.com Git - mirror_frr.git/blob - staticd/static_nht.c
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[mirror_frr.git] / staticd / static_nht.c
1 /*
2 * Static NHT code.
3 * Copyright (C) 2018 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
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)
9 * any later version.
10 *
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
14 * more details.
15 *
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
19 */
20 #include <zebra.h>
21
22 #include "prefix.h"
23 #include "table.h"
24 #include "vrf.h"
25 #include "nexthop.h"
26 #include "srcdest_table.h"
27
28 #include "static_vrf.h"
29 #include "static_routes.h"
30 #include "static_zebra.h"
31 #include "static_nht.h"
32
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,
35 struct vrf *vrf)
36 {
37 struct static_nexthop *nh;
38
39 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
40 if (nh->nh_vrf_id != nh_vrf_id)
41 continue;
42
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)
47 continue;
48
49 if (nhp->family == AF_INET
50 && nhp->u.prefix4.s_addr == nh->addr.ipv4.s_addr)
51 nh->nh_valid = !!nh_num;
52
53 if (nhp->family == AF_INET6
54 && memcmp(&nhp->u.prefix6, &nh->addr.ipv6, IPV6_MAX_BYTELEN)
55 == 0)
56 nh->nh_valid = !!nh_num;
57
58 if (nh->state == STATIC_START)
59 static_zebra_route_add(pn, true);
60 }
61 }
62
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)
66 {
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;
72
73 svrf = vrf->info;
74 if (!svrf)
75 return;
76
77 stable = static_vrf_static_table(afi, safi, svrf);
78 if (!stable)
79 return;
80
81 if (sp) {
82 rn = srcdest_rnode_lookup(stable, sp, NULL);
83 if (rn && rn->info) {
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,
87 nh_vrf_id, vrf);
88 }
89 route_unlock_node(rn);
90 }
91 return;
92 }
93
94 for (rn = route_top(stable); rn; rn = route_next(rn)) {
95 si = static_route_info_from_rnode(rn);
96 if (!si)
97 continue;
98 frr_each(static_path_list, &si->path_list, pn) {
99 static_nht_update_path(pn, nhp, nh_num, nh_vrf_id, vrf);
100 }
101 }
102 }
103
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)
106 {
107
108 struct vrf *vrf;
109
110 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
111 static_nht_update_safi(sp, nhp, nh_num, afi, safi, vrf,
112 nh_vrf_id);
113 }
114
115 static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi,
116 safi_t safi, struct vrf *vrf,
117 vrf_id_t nh_vrf_id)
118 {
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;
125
126 svrf = vrf->info;
127 if (!svrf)
128 return;
129
130 stable = static_vrf_static_table(afi, safi, svrf);
131 if (!stable)
132 return;
133
134 for (rn = route_top(stable); rn; rn = route_next(rn)) {
135 si = static_route_info_from_rnode(rn);
136 if (!si)
137 continue;
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)
141 continue;
142
143 if (nhp->family == AF_INET
144 && nhp->u.prefix4.s_addr
145 != nh->addr.ipv4.s_addr)
146 continue;
147
148 if (nhp->family == AF_INET6
149 && memcmp(&nhp->u.prefix6, &nh->addr.ipv6,
150 16)
151 != 0)
152 continue;
153
154 /*
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
158 * us to start over.
159 */
160 nh->state = STATIC_START;
161 }
162 }
163 }
164 }
165
166 void static_nht_reset_start(struct prefix *nhp, afi_t afi, safi_t safi,
167 vrf_id_t nh_vrf_id)
168 {
169 struct vrf *vrf;
170
171 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
172 static_nht_reset_start_safi(nhp, afi, safi, vrf, nh_vrf_id);
173 }
174
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)
178 {
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;
185
186 svrf = vrf->info;
187 if (!svrf)
188 return;
189
190 stable = static_vrf_static_table(afi, safi, svrf);
191 if (!stable)
192 return;
193
194 rn = srcdest_rnode_lookup(stable, sp, NULL);
195 if (!rn)
196 return;
197 si = rn->info;
198 if (si) {
199 frr_each(static_path_list, &si->path_list, pn) {
200 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
201 nh->state = state;
202 }
203 }
204 }
205
206 route_unlock_node(rn);
207 }
208
209 void static_nht_mark_state(struct prefix *sp, safi_t safi, vrf_id_t vrf_id,
210 enum static_install_states state)
211 {
212 struct vrf *vrf;
213
214 afi_t afi = AFI_IP;
215
216 if (sp->family == AF_INET6)
217 afi = AFI_IP6;
218
219 vrf = vrf_lookup_by_id(vrf_id);
220 if (!vrf || !vrf->info)
221 return;
222
223 static_nht_mark_state_safi(sp, afi, safi, vrf, state);
224 }