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