]>
Commit | Line | Data |
---|---|---|
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_rn(struct route_node *rn, | |
34 | struct prefix *nhp, uint32_t nh_num, | |
35 | vrf_id_t nh_vrf_id, struct vrf *vrf, | |
36 | safi_t safi) | |
37 | { | |
38 | struct static_route *si; | |
39 | ||
40 | for (si = rn->info; si; si = si->next) { | |
41 | if (si->nh_vrf_id != nh_vrf_id) | |
42 | continue; | |
43 | ||
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) | |
48 | continue; | |
49 | ||
50 | if (nhp->family == AF_INET | |
51 | && nhp->u.prefix4.s_addr == si->addr.ipv4.s_addr) | |
52 | si->nh_valid = !!nh_num; | |
53 | ||
54 | if (nhp->family == AF_INET6 | |
55 | && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) == 0) | |
56 | si->nh_valid = !!nh_num; | |
57 | ||
58 | if (si->state == STATIC_START) | |
59 | static_zebra_route_add(rn, si, vrf->vrf_id, safi, 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 | ||
71 | svrf = vrf->info; | |
72 | if (!svrf) | |
73 | return; | |
74 | ||
75 | stable = static_vrf_static_table(afi, safi, svrf); | |
76 | if (!stable) | |
77 | return; | |
78 | ||
79 | if (sp) { | |
80 | rn = srcdest_rnode_lookup(stable, sp, NULL); | |
81 | if (rn) { | |
82 | static_nht_update_rn(rn, nhp, nh_num, nh_vrf_id, | |
83 | vrf, safi); | |
84 | route_unlock_node(rn); | |
85 | } | |
86 | return; | |
87 | } | |
88 | ||
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); | |
91 | ||
92 | } | |
93 | ||
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) | |
96 | { | |
97 | ||
98 | struct vrf *vrf; | |
99 | ||
100 | RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { | |
101 | static_nht_update_safi(sp, nhp, nh_num, afi, SAFI_UNICAST, | |
102 | vrf, nh_vrf_id); | |
103 | static_nht_update_safi(sp, nhp, nh_num, afi, SAFI_MULTICAST, | |
104 | vrf, nh_vrf_id); | |
105 | } | |
106 | } | |
107 | ||
108 | static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi, | |
109 | safi_t safi, struct vrf *vrf, | |
110 | vrf_id_t nh_vrf_id) | |
111 | { | |
112 | struct static_vrf *svrf; | |
113 | struct route_table *stable; | |
114 | struct static_route *si; | |
115 | struct route_node *rn; | |
116 | ||
117 | svrf = vrf->info; | |
118 | if (!svrf) | |
119 | return; | |
120 | ||
121 | stable = static_vrf_static_table(afi, safi, svrf); | |
122 | if (!stable) | |
123 | return; | |
124 | ||
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) | |
128 | continue; | |
129 | ||
130 | if (nhp->family == AF_INET | |
131 | && nhp->u.prefix4.s_addr != si->addr.ipv4.s_addr) | |
132 | continue; | |
133 | ||
134 | if (nhp->family == AF_INET6 | |
135 | && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) != 0) | |
136 | continue; | |
137 | ||
138 | /* | |
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 | |
142 | * over. | |
143 | */ | |
144 | si->state = STATIC_START; | |
145 | } | |
146 | } | |
147 | } | |
148 | ||
149 | void static_nht_reset_start(struct prefix *nhp, afi_t afi, vrf_id_t nh_vrf_id) | |
150 | { | |
151 | struct vrf *vrf; | |
152 | ||
153 | RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { | |
154 | static_nht_reset_start_safi(nhp, afi, SAFI_UNICAST, | |
155 | vrf, nh_vrf_id); | |
156 | static_nht_reset_start_safi(nhp, afi, SAFI_MULTICAST, | |
157 | vrf, nh_vrf_id); | |
158 | } | |
159 | } | |
160 | ||
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) | |
164 | { | |
165 | struct static_vrf *svrf; | |
166 | struct route_table *stable; | |
167 | struct static_route *si; | |
168 | struct route_node *rn; | |
169 | ||
170 | svrf = vrf->info; | |
171 | if (!svrf) | |
172 | return; | |
173 | ||
174 | stable = static_vrf_static_table(afi, safi, svrf); | |
175 | if (!stable) | |
176 | return; | |
177 | ||
178 | rn = srcdest_rnode_lookup(stable, sp, NULL); | |
179 | if (!rn) | |
180 | return; | |
181 | ||
182 | for (si = rn->info; si; si = si->next) | |
183 | si->state = state; | |
184 | ||
185 | route_unlock_node(rn); | |
186 | } | |
187 | ||
188 | void static_nht_mark_state(struct prefix *sp, vrf_id_t vrf_id, | |
189 | enum static_install_states state) | |
190 | { | |
191 | struct vrf *vrf; | |
192 | ||
193 | afi_t afi = AFI_IP; | |
194 | ||
195 | if (sp->family == AF_INET6) | |
196 | afi = AFI_IP6; | |
197 | ||
198 | vrf = vrf_lookup_by_id(vrf_id); | |
199 | if (!vrf || !vrf->info) | |
200 | return; | |
201 | ||
202 | static_nht_mark_state_safi(sp, afi, SAFI_UNICAST, vrf, state); | |
203 | static_nht_mark_state_safi(sp, afi, SAFI_MULTICAST, vrf, state); | |
204 | } |