mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 11:01:48 +00:00
commit
d6716be3d9
@ -1340,6 +1340,16 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
break;
|
||||
}
|
||||
STREAM_GETC(s, nhr->nexthops[i].label_num);
|
||||
if (nhr->nexthops[i].label_num > MPLS_MAX_LABELS) {
|
||||
zlog_warn("%s: invalid number of MPLS labels (%u)",
|
||||
__func__, nhr->nexthops[i].label_num);
|
||||
return false;
|
||||
}
|
||||
if (nhr->nexthops[i].label_num)
|
||||
STREAM_GET(&nhr->nexthops[i].labels[0], s,
|
||||
nhr->nexthops[i].label_num
|
||||
* sizeof(mpls_label_t));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -39,6 +39,46 @@ extern uint32_t total_routes;
|
||||
extern uint32_t installed_routes;
|
||||
extern uint32_t removed_routes;
|
||||
|
||||
DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
|
||||
"sharp watch nexthop X:X::X:X$nhop",
|
||||
"Sharp routing Protocol\n"
|
||||
"Watch for changes\n"
|
||||
"Watch for nexthop changes\n"
|
||||
"The v6 nexthop to signal for watching\n")
|
||||
{
|
||||
struct prefix p;
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
|
||||
p.prefixlen = 128;
|
||||
memcpy(&p.u.prefix6, &nhop, 16);
|
||||
p.family = AF_INET6;
|
||||
|
||||
sharp_zebra_nexthop_watch(&p, true);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
|
||||
"sharp watch nexthop A.B.C.D$nhop",
|
||||
"Sharp routing Protocol\n"
|
||||
"Watch for changes\n"
|
||||
"Watch for nexthop changes\n"
|
||||
"The v4 nexthop to signal for watching\n")
|
||||
{
|
||||
struct prefix p;
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
|
||||
p.prefixlen = 32;
|
||||
p.u.prefix4 = nhop;
|
||||
p.family = AF_INET;
|
||||
|
||||
sharp_zebra_nexthop_watch(&p, true);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (install_routes,
|
||||
install_routes_cmd,
|
||||
"sharp install routes A.B.C.D$start nexthop A.B.C.D$nexthop (1-1000000)$routes",
|
||||
@ -147,5 +187,7 @@ void sharp_vty_init(void)
|
||||
install_element(ENABLE_NODE, &install_routes_cmd);
|
||||
install_element(ENABLE_NODE, &remove_routes_cmd);
|
||||
install_element(ENABLE_NODE, &vrf_label_cmd);
|
||||
install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
|
||||
install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
|
||||
return;
|
||||
}
|
||||
|
@ -214,6 +214,65 @@ void route_delete(struct prefix *p)
|
||||
return;
|
||||
}
|
||||
|
||||
void sharp_zebra_nexthop_watch(struct prefix *p, bool watch)
|
||||
{
|
||||
int command = ZEBRA_NEXTHOP_REGISTER;
|
||||
|
||||
if (!watch)
|
||||
command = ZEBRA_NEXTHOP_UNREGISTER;
|
||||
|
||||
zclient_send_rnh(zclient, command, p, true, VRF_DEFAULT);
|
||||
}
|
||||
|
||||
static int sharp_nexthop_update(int command, struct zclient *zclient,
|
||||
zebra_size_t length, vrf_id_t vrf_id)
|
||||
{
|
||||
struct zapi_route nhr;
|
||||
char buf[PREFIX_STRLEN];
|
||||
int i;
|
||||
|
||||
if (!zapi_nexthop_update_decode(zclient->ibuf, &nhr)) {
|
||||
zlog_warn("%s: Decode of update failed", __PRETTY_FUNCTION__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
zlog_debug("Received update for %s",
|
||||
prefix2str(&nhr.prefix, buf, sizeof(buf)));
|
||||
for (i = 0; i < nhr.nexthop_num; i++) {
|
||||
struct zapi_nexthop *znh = &nhr.nexthops[i];
|
||||
|
||||
switch (znh->type) {
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
zlog_debug(
|
||||
"\tNexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d",
|
||||
inet_ntop(AF_INET, &znh->gate.ipv4.s_addr, buf,
|
||||
sizeof(buf)),
|
||||
znh->type, znh->ifindex, znh->vrf_id,
|
||||
znh->label_num);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
zlog_debug(
|
||||
"\tNexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d",
|
||||
inet_ntop(AF_INET6, &znh->gate.ipv6, buf,
|
||||
sizeof(buf)),
|
||||
znh->type, znh->ifindex, znh->vrf_id,
|
||||
znh->label_num);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
zlog_debug("\tNexthop IFINDEX: %d, ifindex: %d",
|
||||
znh->type, znh->ifindex);
|
||||
break;
|
||||
case NEXTHOP_TYPE_BLACKHOLE:
|
||||
zlog_debug("\tNexthop blackhole");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern struct zebra_privs_t sharp_privs;
|
||||
|
||||
void sharp_zebra_init(void)
|
||||
@ -231,4 +290,5 @@ void sharp_zebra_init(void)
|
||||
zclient->interface_address_add = interface_address_add;
|
||||
zclient->interface_address_delete = interface_address_delete;
|
||||
zclient->route_notify_owner = route_notify_owner;
|
||||
zclient->nexthop_update = sharp_nexthop_update;
|
||||
}
|
||||
|
@ -27,4 +27,5 @@ extern void sharp_zebra_init(void);
|
||||
extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label);
|
||||
extern void route_add(struct prefix *p, struct nexthop *nh);
|
||||
extern void route_delete(struct prefix *p);
|
||||
extern void sharp_zebra_nexthop_watch(struct prefix *p, bool watch);
|
||||
#endif
|
||||
|
@ -2254,6 +2254,19 @@ void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf,
|
||||
fec_print(rn->info, vty);
|
||||
}
|
||||
|
||||
static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop,
|
||||
enum lsp_types_t type, mpls_label_t label)
|
||||
{
|
||||
if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE)
|
||||
nexthop_add_labels(nexthop, type, 1, &label);
|
||||
else if (!add && nexthop->nh_label_type == type)
|
||||
nexthop_del_labels(nexthop);
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Install/uninstall a FEC-To-NHLFE (FTN) binding.
|
||||
*/
|
||||
@ -2266,6 +2279,7 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
|
||||
struct route_node *rn;
|
||||
struct route_entry *re;
|
||||
struct nexthop *nexthop;
|
||||
bool found;
|
||||
|
||||
/* Lookup table. */
|
||||
table = zebra_vrf_table(family2afi(prefix->family), SAFI_UNICAST,
|
||||
@ -2285,6 +2299,7 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
|
||||
if (re == NULL)
|
||||
return -1;
|
||||
|
||||
found = false;
|
||||
for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) {
|
||||
switch (nexthop->type) {
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
@ -2297,7 +2312,11 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
|
||||
if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
|
||||
&& nexthop->ifindex != ifindex)
|
||||
continue;
|
||||
goto found;
|
||||
if (!mpls_ftn_update_nexthop(add, nexthop, type,
|
||||
out_label))
|
||||
return 0;
|
||||
found = true;
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||
if (gtype != NEXTHOP_TYPE_IPV6
|
||||
@ -2308,21 +2327,18 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
|
||||
if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
|
||||
&& nexthop->ifindex != ifindex)
|
||||
continue;
|
||||
goto found;
|
||||
if (!mpls_ftn_update_nexthop(add, nexthop, type,
|
||||
out_label))
|
||||
return 0;
|
||||
found = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* nexthop not found */
|
||||
return -1;
|
||||
|
||||
found:
|
||||
if (add && nexthop->nh_label_type == ZEBRA_LSP_NONE)
|
||||
nexthop_add_labels(nexthop, type, 1, &out_label);
|
||||
else if (!add && nexthop->nh_label_type == type)
|
||||
nexthop_del_labels(nexthop);
|
||||
else
|
||||
return 0;
|
||||
if (!found)
|
||||
return -1;
|
||||
|
||||
SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
|
||||
SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
|
||||
|
@ -986,7 +986,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
|
||||
struct route_entry *re;
|
||||
unsigned long nump;
|
||||
u_char num;
|
||||
struct nexthop *nexthop;
|
||||
struct nexthop *nh;
|
||||
struct route_node *rn;
|
||||
int cmd = (type == RNH_IMPORT_CHECK_TYPE) ? ZEBRA_IMPORT_CHECK_UPDATE
|
||||
: ZEBRA_NEXTHOP_UPDATE;
|
||||
@ -1022,32 +1022,40 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
|
||||
num = 0;
|
||||
nump = stream_get_endp(s);
|
||||
stream_putc(s, 0);
|
||||
for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next)
|
||||
if ((CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
|
||||
|| CHECK_FLAG(nexthop->flags,
|
||||
NEXTHOP_FLAG_RECURSIVE))
|
||||
&& CHECK_FLAG(nexthop->flags,
|
||||
NEXTHOP_FLAG_ACTIVE)) {
|
||||
stream_putc(s, nexthop->type);
|
||||
switch (nexthop->type) {
|
||||
for (nh = re->ng.nexthop; nh; nh = nh->next)
|
||||
if ((CHECK_FLAG(nh->flags, NEXTHOP_FLAG_FIB)
|
||||
|| CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE))
|
||||
&& CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE)) {
|
||||
stream_putc(s, nh->type);
|
||||
switch (nh->type) {
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
stream_put_in_addr(s,
|
||||
&nexthop->gate.ipv4);
|
||||
stream_putl(s, nexthop->ifindex);
|
||||
stream_put_in_addr(s, &nh->gate.ipv4);
|
||||
stream_putl(s, nh->ifindex);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IFINDEX:
|
||||
stream_putl(s, nexthop->ifindex);
|
||||
stream_putl(s, nh->ifindex);
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6:
|
||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||
stream_put(s, &nexthop->gate.ipv6, 16);
|
||||
stream_putl(s, nexthop->ifindex);
|
||||
stream_put(s, &nh->gate.ipv6, 16);
|
||||
stream_putl(s, nh->ifindex);
|
||||
break;
|
||||
default:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
if (nh->nh_label) {
|
||||
stream_putc(s,
|
||||
nh->nh_label->num_labels);
|
||||
if (nh->nh_label->num_labels)
|
||||
stream_put(
|
||||
s,
|
||||
&nh->nh_label->label[0],
|
||||
nh->nh_label->num_labels
|
||||
* sizeof(mpls_label_t));
|
||||
} else
|
||||
stream_putc(s, 0);
|
||||
num++;
|
||||
}
|
||||
stream_putc_at(s, nump, num);
|
||||
|
Loading…
Reference in New Issue
Block a user