]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
718e3744 | 2 | /* RIPd and zebra interface. |
3 | * Copyright (C) 1997, 1999 Kunihiro Ishiguro <kunihiro@zebra.org> | |
718e3744 | 4 | */ |
5 | ||
6 | #include <zebra.h> | |
7 | ||
8 | #include "command.h" | |
9 | #include "prefix.h" | |
bce8e868 | 10 | #include "table.h" |
718e3744 | 11 | #include "stream.h" |
bce8e868 | 12 | #include "memory.h" |
718e3744 | 13 | #include "zclient.h" |
14 | #include "log.h" | |
7076bb2f | 15 | #include "vrf.h" |
718e3744 | 16 | #include "ripd/ripd.h" |
17 | #include "ripd/rip_debug.h" | |
dc63bfd4 | 18 | #include "ripd/rip_interface.h" |
718e3744 | 19 | |
20 | /* All information about zebra. */ | |
21 | struct zclient *zclient = NULL; | |
6b0655a2 | 22 | |
bce8e868 | 23 | /* Send ECMP routes to zebra. */ |
045c5389 RW |
24 | static void rip_zebra_ipv4_send(struct rip *rip, struct route_node *rp, |
25 | uint8_t cmd) | |
718e3744 | 26 | { |
d62a17ae | 27 | struct list *list = (struct list *)rp->info; |
c9fb3e23 RW |
28 | struct zapi_route api; |
29 | struct zapi_nexthop *api_nh; | |
d62a17ae | 30 | struct listnode *listnode = NULL; |
31 | struct rip_info *rinfo = NULL; | |
32 | int count = 0; | |
33 | ||
c9fb3e23 | 34 | memset(&api, 0, sizeof(api)); |
ae7b826a | 35 | api.vrf_id = rip->vrf->vrf_id; |
d00061ea | 36 | api.type = ZEBRA_ROUTE_RIP; |
d00061ea RW |
37 | api.safi = SAFI_UNICAST; |
38 | ||
d00061ea RW |
39 | SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); |
40 | for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { | |
a74e593b RW |
41 | if (count >= MULTIPATH_NUM) |
42 | break; | |
c9fb3e23 | 43 | api_nh = &api.nexthops[count]; |
ae7b826a | 44 | api_nh->vrf_id = rip->vrf->vrf_id; |
dd127197 | 45 | api_nh->gate = rinfo->nh.gate; |
c9fb3e23 RW |
46 | api_nh->type = NEXTHOP_TYPE_IPV4; |
47 | if (cmd == ZEBRA_ROUTE_ADD) | |
d00061ea RW |
48 | SET_FLAG(rinfo->flags, RIP_RTF_FIB); |
49 | else | |
50 | UNSET_FLAG(rinfo->flags, RIP_RTF_FIB); | |
c9fb3e23 | 51 | count++; |
d00061ea | 52 | } |
d62a17ae | 53 | |
c9fb3e23 | 54 | api.prefix = rp->p; |
d00061ea | 55 | api.nexthop_num = count; |
d62a17ae | 56 | |
d00061ea | 57 | rinfo = listgetdata(listhead(list)); |
d62a17ae | 58 | |
d00061ea RW |
59 | SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); |
60 | api.metric = rinfo->metric; | |
d62a17ae | 61 | |
d00061ea RW |
62 | if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) { |
63 | SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); | |
64 | api.distance = rinfo->distance; | |
65 | } | |
d62a17ae | 66 | |
d00061ea RW |
67 | if (rinfo->tag) { |
68 | SET_FLAG(api.message, ZAPI_MESSAGE_TAG); | |
69 | api.tag = rinfo->tag; | |
70 | } | |
d62a17ae | 71 | |
c9fb3e23 | 72 | zclient_route_send(cmd, zclient, &api); |
d00061ea RW |
73 | |
74 | if (IS_RIP_DEBUG_ZEBRA) { | |
75 | if (rip->ecmp) | |
53bb7f9b | 76 | zlog_debug("%s: %pFX nexthops %d", |
c9fb3e23 | 77 | (cmd == ZEBRA_ROUTE_ADD) |
d00061ea RW |
78 | ? "Install into zebra" |
79 | : "Delete from zebra", | |
53bb7f9b | 80 | &rp->p, count); |
d00061ea | 81 | else |
53bb7f9b | 82 | zlog_debug("%s: %pFX", |
c9fb3e23 | 83 | (cmd == ZEBRA_ROUTE_ADD) |
d00061ea | 84 | ? "Install into zebra" |
53bb7f9b | 85 | : "Delete from zebra", &rp->p); |
d62a17ae | 86 | } |
d00061ea | 87 | |
c08a2107 | 88 | rip->counters.route_changes++; |
718e3744 | 89 | } |
90 | ||
bce8e868 | 91 | /* Add/update ECMP routes to zebra. */ |
045c5389 | 92 | void rip_zebra_ipv4_add(struct rip *rip, struct route_node *rp) |
718e3744 | 93 | { |
045c5389 | 94 | rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_ADD); |
bce8e868 | 95 | } |
718e3744 | 96 | |
bce8e868 | 97 | /* Delete ECMP routes from zebra. */ |
045c5389 | 98 | void rip_zebra_ipv4_delete(struct rip *rip, struct route_node *rp) |
bce8e868 | 99 | { |
045c5389 | 100 | rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_DELETE); |
718e3744 | 101 | } |
102 | ||
103 | /* Zebra route add and delete treatment. */ | |
121f9dee | 104 | static int rip_zebra_read_route(ZAPI_CALLBACK_ARGS) |
718e3744 | 105 | { |
045c5389 | 106 | struct rip *rip; |
74489921 | 107 | struct zapi_route api; |
3f5682c8 | 108 | struct nexthop nh; |
d62a17ae | 109 | |
045c5389 | 110 | rip = rip_lookup_by_vrf_id(vrf_id); |
d62a17ae | 111 | if (!rip) |
112 | return 0; | |
113 | ||
74489921 RW |
114 | if (zapi_route_decode(zclient->ibuf, &api) < 0) |
115 | return -1; | |
116 | ||
3f5682c8 DS |
117 | memset(&nh, 0, sizeof(nh)); |
118 | nh.type = api.nexthops[0].type; | |
119 | nh.gate.ipv4 = api.nexthops[0].gate.ipv4; | |
120 | nh.ifindex = api.nexthops[0].ifindex; | |
d62a17ae | 121 | |
122 | /* Then fetch IPv4 prefixes. */ | |
121f9dee | 123 | if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) |
045c5389 | 124 | rip_redistribute_add(rip, api.type, RIP_ROUTE_REDISTRIBUTE, |
3f5682c8 | 125 | (struct prefix_ipv4 *)&api.prefix, &nh, |
996c9314 | 126 | api.metric, api.distance, api.tag); |
121f9dee | 127 | else if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) |
045c5389 | 128 | rip_redistribute_delete(rip, api.type, RIP_ROUTE_REDISTRIBUTE, |
74489921 | 129 | (struct prefix_ipv4 *)&api.prefix, |
3f5682c8 | 130 | nh.ifindex); |
d62a17ae | 131 | |
132 | return 0; | |
718e3744 | 133 | } |
134 | ||
045c5389 | 135 | void rip_redistribute_conf_update(struct rip *rip, int type) |
718e3744 | 136 | { |
ad21f675 DS |
137 | zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, |
138 | type, 0, rip->vrf->vrf_id); | |
718e3744 | 139 | } |
6b0655a2 | 140 | |
045c5389 | 141 | void rip_redistribute_conf_delete(struct rip *rip, int type) |
718e3744 | 142 | { |
d62a17ae | 143 | if (zclient->sock > 0) |
144 | zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, | |
ae7b826a | 145 | AFI_IP, type, 0, rip->vrf->vrf_id); |
718e3744 | 146 | |
d62a17ae | 147 | /* Remove the routes from RIP table. */ |
045c5389 | 148 | rip_redistribute_withdraw(rip, type); |
718e3744 | 149 | } |
150 | ||
045c5389 | 151 | int rip_redistribute_check(struct rip *rip, int type) |
718e3744 | 152 | { |
f9120f71 | 153 | return rip->redist[type].enabled; |
718e3744 | 154 | } |
155 | ||
f9120f71 | 156 | void rip_redistribute_enable(struct rip *rip) |
718e3744 | 157 | { |
908f0020 | 158 | for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { |
f9120f71 | 159 | if (!rip_redistribute_check(rip, i)) |
908f0020 | 160 | continue; |
d62a17ae | 161 | |
f9120f71 RW |
162 | zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, |
163 | i, 0, rip->vrf->vrf_id); | |
164 | } | |
165 | } | |
d62a17ae | 166 | |
f9120f71 RW |
167 | void rip_redistribute_disable(struct rip *rip) |
168 | { | |
169 | for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { | |
170 | if (!rip_redistribute_check(rip, i)) | |
171 | continue; | |
172 | ||
173 | zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, | |
174 | AFI_IP, i, 0, rip->vrf->vrf_id); | |
d62a17ae | 175 | } |
16705130 | 176 | } |
177 | ||
045c5389 | 178 | void rip_show_redistribute_config(struct vty *vty, struct rip *rip) |
718e3744 | 179 | { |
908f0020 | 180 | for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { |
d00061ea | 181 | if (i == zclient->redist_default |
f9120f71 | 182 | || !rip_redistribute_check(rip, i)) |
d00061ea RW |
183 | continue; |
184 | ||
908f0020 | 185 | vty_out(vty, " %s", zebra_route_string(i)); |
d00061ea | 186 | } |
718e3744 | 187 | } |
188 | ||
ae7b826a RW |
189 | void rip_zebra_vrf_register(struct vrf *vrf) |
190 | { | |
191 | if (vrf->vrf_id == VRF_DEFAULT) | |
192 | return; | |
193 | ||
194 | if (IS_RIP_DEBUG_EVENT) | |
195 | zlog_debug("%s: register VRF %s(%u) to zebra", __func__, | |
196 | vrf->name, vrf->vrf_id); | |
197 | ||
198 | zclient_send_reg_requests(zclient, vrf->vrf_id); | |
199 | } | |
200 | ||
201 | void rip_zebra_vrf_deregister(struct vrf *vrf) | |
202 | { | |
203 | if (vrf->vrf_id == VRF_DEFAULT) | |
204 | return; | |
205 | ||
206 | if (IS_RIP_DEBUG_EVENT) | |
207 | zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__, | |
208 | vrf->name, vrf->vrf_id); | |
209 | ||
210 | zclient_send_dereg_requests(zclient, vrf->vrf_id); | |
211 | } | |
212 | ||
d62a17ae | 213 | static void rip_zebra_connected(struct zclient *zclient) |
7076bb2f | 214 | { |
d62a17ae | 215 | zclient_send_reg_requests(zclient, VRF_DEFAULT); |
7076bb2f FL |
216 | } |
217 | ||
a243d1db DL |
218 | zclient_handler *const rip_handlers[] = { |
219 | [ZEBRA_INTERFACE_ADDRESS_ADD] = rip_interface_address_add, | |
220 | [ZEBRA_INTERFACE_ADDRESS_DELETE] = rip_interface_address_delete, | |
221 | [ZEBRA_INTERFACE_VRF_UPDATE] = rip_interface_vrf_update, | |
222 | [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = rip_zebra_read_route, | |
223 | [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = rip_zebra_read_route, | |
224 | }; | |
225 | ||
cd9d0537 | 226 | void rip_zclient_init(struct event_loop *master) |
718e3744 | 227 | { |
d62a17ae | 228 | /* Set default value to the zebra client structure. */ |
a243d1db DL |
229 | zclient = zclient_new(master, &zclient_options_default, rip_handlers, |
230 | array_size(rip_handlers)); | |
342213ea | 231 | zclient_init(zclient, ZEBRA_ROUTE_RIP, 0, &ripd_privs); |
d62a17ae | 232 | zclient->zebra_connected = rip_zebra_connected; |
718e3744 | 233 | } |
a2f9eb82 | 234 | |
d62a17ae | 235 | void rip_zclient_stop(void) |
a2f9eb82 | 236 | { |
d62a17ae | 237 | zclient_stop(zclient); |
238 | zclient_free(zclient); | |
a2f9eb82 | 239 | } |