]> git.proxmox.com Git - mirror_frr.git/blame - ripngd/ripng_zebra.c
ripng: Implement `allow-ecmp X` command
[mirror_frr.git] / ripngd / ripng_zebra.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/*
3 * RIPngd and zebra interface.
4 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
718e3744 5 */
6
7#include <zebra.h>
8
9#include "command.h"
10#include "prefix.h"
fe08ba7e 11#include "agg_table.h"
718e3744 12#include "stream.h"
c880b636 13#include "memory.h"
718e3744 14#include "routemap.h"
15#include "zclient.h"
16#include "log.h"
17
18#include "ripngd/ripngd.h"
c880b636 19#include "ripngd/ripng_debug.h"
718e3744 20
21/* All information about zebra. */
22struct zclient *zclient = NULL;
57aedde6 23uint32_t zebra_ecmp_count = MULTIPATH_NUM;
718e3744 24
c880b636 25/* Send ECMP routes to zebra. */
5c84b9a5
RW
26static void ripng_zebra_ipv6_send(struct ripng *ripng, struct agg_node *rp,
27 uint8_t cmd)
718e3744 28{
d62a17ae 29 struct list *list = (struct list *)rp->info;
c9fb3e23
RW
30 struct zapi_route api;
31 struct zapi_nexthop *api_nh;
d62a17ae 32 struct listnode *listnode = NULL;
33 struct ripng_info *rinfo = NULL;
57aedde6 34 uint32_t count = 0;
26a3ffd6 35 const struct prefix *p = agg_node_get_prefix(rp);
d62a17ae 36
c9fb3e23 37 memset(&api, 0, sizeof(api));
dde7b15b 38 api.vrf_id = ripng->vrf->vrf_id;
d00061ea 39 api.type = ZEBRA_ROUTE_RIPNG;
d00061ea 40 api.safi = SAFI_UNICAST;
26a3ffd6 41 api.prefix = *p;
d62a17ae 42
d00061ea 43 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
d00061ea 44 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
57aedde6 45 if (count >= zebra_ecmp_count)
a74e593b 46 break;
c9fb3e23 47 api_nh = &api.nexthops[count];
dde7b15b 48 api_nh->vrf_id = ripng->vrf->vrf_id;
c9fb3e23
RW
49 api_nh->gate.ipv6 = rinfo->nexthop;
50 api_nh->ifindex = rinfo->ifindex;
51 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
d00061ea 52 count++;
c9fb3e23 53 if (cmd == ZEBRA_ROUTE_ADD)
d00061ea
RW
54 SET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
55 else
56 UNSET_FLAG(rinfo->flags, RIPNG_RTF_FIB);
57 }
d62a17ae 58
d00061ea 59 api.nexthop_num = count;
d62a17ae 60
d00061ea 61 rinfo = listgetdata(listhead(list));
d62a17ae 62
d00061ea
RW
63 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
64 api.metric = rinfo->metric;
d62a17ae 65
d00061ea
RW
66 if (rinfo->tag) {
67 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
68 api.tag = rinfo->tag;
69 }
d62a17ae 70
c9fb3e23 71 zclient_route_send(cmd, zclient, &api);
d00061ea
RW
72
73 if (IS_RIPNG_DEBUG_ZEBRA) {
74 if (ripng->ecmp)
26a3ffd6 75 zlog_debug("%s: %pRN nexthops %d",
c9fb3e23 76 (cmd == ZEBRA_ROUTE_ADD)
d00061ea
RW
77 ? "Install into zebra"
78 : "Delete from zebra",
26a3ffd6 79 rp, count);
d00061ea 80 else
26a3ffd6
DS
81 zlog_debug("%s: %pRN",
82 (cmd == ZEBRA_ROUTE_ADD)
83 ? "Install into zebra"
84 : "Delete from zebra",
85 rp);
d62a17ae 86 }
718e3744 87}
88
c880b636 89/* Add/update ECMP routes to zebra. */
5c84b9a5 90void ripng_zebra_ipv6_add(struct ripng *ripng, struct agg_node *rp)
718e3744 91{
5c84b9a5 92 ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_ADD);
c880b636 93}
718e3744 94
c880b636 95/* Delete ECMP routes from zebra. */
5c84b9a5 96void ripng_zebra_ipv6_delete(struct ripng *ripng, struct agg_node *rp)
c880b636 97{
5c84b9a5 98 ripng_zebra_ipv6_send(ripng, rp, ZEBRA_ROUTE_DELETE);
718e3744 99}
100
101/* Zebra route add and delete treatment. */
121f9dee 102static int ripng_zebra_read_route(ZAPI_CALLBACK_ARGS)
718e3744 103{
5c84b9a5 104 struct ripng *ripng;
74489921 105 struct zapi_route api;
d62a17ae 106 struct in6_addr nexthop;
74489921 107 unsigned long ifindex;
d62a17ae 108
5c84b9a5
RW
109 ripng = ripng_lookup_by_vrf_id(vrf_id);
110 if (!ripng)
111 return 0;
112
74489921
RW
113 if (zapi_route_decode(zclient->ibuf, &api) < 0)
114 return -1;
d62a17ae 115
74489921
RW
116 /* we completely ignore srcdest routes for now. */
117 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
118 return 0;
d62a17ae 119
9fb2b879
DS
120 if (IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6))
121 return 0;
122
74489921
RW
123 nexthop = api.nexthops[0].gate.ipv6;
124 ifindex = api.nexthops[0].ifindex;
d62a17ae 125
121f9dee 126 if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
5c84b9a5
RW
127 ripng_redistribute_add(ripng, api.type,
128 RIPNG_ROUTE_REDISTRIBUTE,
74489921 129 (struct prefix_ipv6 *)&api.prefix,
d62a17ae 130 ifindex, &nexthop, api.tag);
131 else
5c84b9a5
RW
132 ripng_redistribute_delete(
133 ripng, api.type, RIPNG_ROUTE_REDISTRIBUTE,
134 (struct prefix_ipv6 *)&api.prefix, ifindex);
d62a17ae 135
136 return 0;
718e3744 137}
138
5c84b9a5 139void ripng_redistribute_conf_update(struct ripng *ripng, int type)
718e3744 140{
2afebed2
DS
141 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6,
142 type, 0, ripng->vrf->vrf_id);
db2038c7 143}
7076bb2f 144
5c84b9a5 145void ripng_redistribute_conf_delete(struct ripng *ripng, int type)
db2038c7 146{
d62a17ae 147 if (zclient->sock > 0)
148 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
dde7b15b 149 AFI_IP6, type, 0, ripng->vrf->vrf_id);
718e3744 150
5c84b9a5 151 ripng_redistribute_withdraw(ripng, type);
718e3744 152}
153
5c84b9a5 154int ripng_redistribute_check(struct ripng *ripng, int type)
a94434b6 155{
f9120f71 156 return ripng->redist[type].enabled;
a94434b6 157}
158
f9120f71 159void ripng_redistribute_enable(struct ripng *ripng)
a94434b6 160{
db2038c7 161 for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
f9120f71 162 if (!ripng_redistribute_check(ripng, i))
db2038c7 163 continue;
d62a17ae 164
f9120f71
RW
165 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient,
166 AFI_IP6, i, 0, ripng->vrf->vrf_id);
167 }
168}
d62a17ae 169
f9120f71
RW
170void ripng_redistribute_disable(struct ripng *ripng)
171{
172 for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
173 if (!ripng_redistribute_check(ripng, i))
174 continue;
718e3744 175
f9120f71
RW
176 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
177 AFI_IP6, i, 0, ripng->vrf->vrf_id);
d62a17ae 178 }
718e3744 179}
180
5c84b9a5 181void ripng_redistribute_write(struct vty *vty, struct ripng *ripng)
718e3744 182{
d62a17ae 183 int i;
184
d00061ea
RW
185 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
186 if (i == zclient->redist_default
f9120f71 187 || !ripng_redistribute_check(ripng, i))
d00061ea
RW
188 continue;
189
db2038c7 190 vty_out(vty, " %s", zebra_route_string(i));
d00061ea 191 }
718e3744 192}
193
dde7b15b
RW
194void ripng_zebra_vrf_register(struct vrf *vrf)
195{
196 if (vrf->vrf_id == VRF_DEFAULT)
197 return;
198
199 if (IS_RIPNG_DEBUG_EVENT)
200 zlog_debug("%s: register VRF %s(%u) to zebra", __func__,
201 vrf->name, vrf->vrf_id);
202
203 zclient_send_reg_requests(zclient, vrf->vrf_id);
204}
205
206void ripng_zebra_vrf_deregister(struct vrf *vrf)
207{
208 if (vrf->vrf_id == VRF_DEFAULT)
209 return;
210
211 if (IS_RIPNG_DEBUG_EVENT)
212 zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__,
213 vrf->name, vrf->vrf_id);
214
215 zclient_send_dereg_requests(zclient, vrf->vrf_id);
216}
217
d62a17ae 218static void ripng_zebra_connected(struct zclient *zclient)
7076bb2f 219{
d62a17ae 220 zclient_send_reg_requests(zclient, VRF_DEFAULT);
7076bb2f
FL
221}
222
a243d1db
DL
223static zclient_handler *const ripng_handlers[] = {
224 [ZEBRA_INTERFACE_ADDRESS_ADD] = ripng_interface_address_add,
225 [ZEBRA_INTERFACE_ADDRESS_DELETE] = ripng_interface_address_delete,
226 [ZEBRA_INTERFACE_VRF_UPDATE] = ripng_interface_vrf_update,
227 [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ripng_zebra_read_route,
228 [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ripng_zebra_read_route,
229};
230
57aedde6
DA
231static void ripng_zebra_capabilities(struct zclient_capabilities *cap)
232{
233 zebra_ecmp_count = MIN(cap->ecmp, zebra_ecmp_count);
234}
235
718e3744 236/* Initialize zebra structure and it's commands. */
cd9d0537 237void zebra_init(struct event_loop *master)
718e3744 238{
d62a17ae 239 /* Allocate zebra structure. */
a243d1db
DL
240 zclient = zclient_new(master, &zclient_options_default, ripng_handlers,
241 array_size(ripng_handlers));
342213ea 242 zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0, &ripngd_privs);
d62a17ae 243
244 zclient->zebra_connected = ripng_zebra_connected;
57aedde6 245 zclient->zebra_capabilities = ripng_zebra_capabilities;
718e3744 246}
7feb9237 247
d62a17ae 248void ripng_zebra_stop(void)
7feb9237 249{
d62a17ae 250 zclient_stop(zclient);
251 zclient_free(zclient);
7feb9237 252}