]> git.proxmox.com Git - mirror_frr.git/blob - staticd/static_nht.c
Merge pull request #8930 from pjdruddy/ospf6_packet_debug
[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 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)
37 {
38 struct static_nexthop *nh;
39
40 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
41 if (nh->nh_vrf_id != nh_vrf_id)
42 continue;
43
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)
48 continue;
49
50 if (nhp->family == AF_INET
51 && nhp->u.prefix4.s_addr == nh->addr.ipv4.s_addr)
52 nh->nh_valid = !!nh_num;
53
54 if (nhp->family == AF_INET6
55 && memcmp(&nhp->u.prefix6, &nh->addr.ipv6, IPV6_MAX_BYTELEN)
56 == 0)
57 nh->nh_valid = !!nh_num;
58
59 if (nh->state == STATIC_START)
60 static_zebra_route_add(rn, pn, safi, true);
61 }
62 }
63
64 static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp,
65 uint32_t nh_num, afi_t afi, safi_t safi,
66 struct vrf *vrf, vrf_id_t nh_vrf_id)
67 {
68 struct route_table *stable;
69 struct static_vrf *svrf;
70 struct route_node *rn;
71 struct static_path *pn;
72 struct static_route_info *si;
73
74 svrf = vrf->info;
75 if (!svrf)
76 return;
77
78 stable = static_vrf_static_table(afi, safi, svrf);
79 if (!stable)
80 return;
81
82 if (sp) {
83 rn = srcdest_rnode_lookup(stable, sp, NULL);
84 if (rn && rn->info) {
85 si = static_route_info_from_rnode(rn);
86 frr_each(static_path_list, &si->path_list, pn) {
87 static_nht_update_path(rn, pn, nhp, nh_num,
88 nh_vrf_id, vrf, safi);
89 }
90 route_unlock_node(rn);
91 }
92 return;
93 }
94
95 for (rn = route_top(stable); rn; rn = route_next(rn)) {
96 si = static_route_info_from_rnode(rn);
97 if (!si)
98 continue;
99 frr_each(static_path_list, &si->path_list, pn) {
100 static_nht_update_path(rn, pn, nhp, nh_num, nh_vrf_id,
101 vrf, safi);
102 }
103 }
104 }
105
106 void static_nht_update(struct prefix *sp, struct prefix *nhp,
107 uint32_t nh_num, afi_t afi, vrf_id_t nh_vrf_id)
108 {
109
110 struct vrf *vrf;
111
112 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
113 static_nht_update_safi(sp, nhp, nh_num, afi, SAFI_UNICAST,
114 vrf, nh_vrf_id);
115 static_nht_update_safi(sp, nhp, nh_num, afi, SAFI_MULTICAST,
116 vrf, nh_vrf_id);
117 }
118 }
119
120 static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi,
121 safi_t safi, struct vrf *vrf,
122 vrf_id_t nh_vrf_id)
123 {
124 struct static_vrf *svrf;
125 struct route_table *stable;
126 struct static_nexthop *nh;
127 struct static_path *pn;
128 struct route_node *rn;
129 struct static_route_info *si;
130
131 svrf = vrf->info;
132 if (!svrf)
133 return;
134
135 stable = static_vrf_static_table(afi, safi, svrf);
136 if (!stable)
137 return;
138
139 for (rn = route_top(stable); rn; rn = route_next(rn)) {
140 si = static_route_info_from_rnode(rn);
141 if (!si)
142 continue;
143 frr_each(static_path_list, &si->path_list, pn) {
144 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
145 if (nh->nh_vrf_id != nh_vrf_id)
146 continue;
147
148 if (nhp->family == AF_INET
149 && nhp->u.prefix4.s_addr
150 != nh->addr.ipv4.s_addr)
151 continue;
152
153 if (nhp->family == AF_INET6
154 && memcmp(&nhp->u.prefix6, &nh->addr.ipv6,
155 16)
156 != 0)
157 continue;
158
159 /*
160 * We've been told that a nexthop we
161 * depend on has changed in some manner,
162 * so reset the state machine to allow
163 * us to start over.
164 */
165 nh->state = STATIC_START;
166 }
167 }
168 }
169 }
170
171 void static_nht_reset_start(struct prefix *nhp, afi_t afi, vrf_id_t nh_vrf_id)
172 {
173 struct vrf *vrf;
174
175 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
176 static_nht_reset_start_safi(nhp, afi, SAFI_UNICAST,
177 vrf, nh_vrf_id);
178 static_nht_reset_start_safi(nhp, afi, SAFI_MULTICAST,
179 vrf, nh_vrf_id);
180 }
181 }
182
183 static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi,
184 safi_t safi, struct vrf *vrf,
185 enum static_install_states state)
186 {
187 struct static_vrf *svrf;
188 struct route_table *stable;
189 struct route_node *rn;
190 struct static_nexthop *nh;
191 struct static_path *pn;
192 struct static_route_info *si;
193
194 svrf = vrf->info;
195 if (!svrf)
196 return;
197
198 stable = static_vrf_static_table(afi, safi, svrf);
199 if (!stable)
200 return;
201
202 rn = srcdest_rnode_lookup(stable, sp, NULL);
203 if (!rn)
204 return;
205 si = rn->info;
206 if (si) {
207 frr_each(static_path_list, &si->path_list, pn) {
208 frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
209 nh->state = state;
210 }
211 }
212 }
213
214 route_unlock_node(rn);
215 }
216
217 void static_nht_mark_state(struct prefix *sp, vrf_id_t vrf_id,
218 enum static_install_states state)
219 {
220 struct vrf *vrf;
221
222 afi_t afi = AFI_IP;
223
224 if (sp->family == AF_INET6)
225 afi = AFI_IP6;
226
227 vrf = vrf_lookup_by_id(vrf_id);
228 if (!vrf || !vrf->info)
229 return;
230
231 static_nht_mark_state_safi(sp, afi, SAFI_UNICAST, vrf, state);
232 static_nht_mark_state_safi(sp, afi, SAFI_MULTICAST, vrf, state);
233 }