|
6 | 6 | #include "rt_grout.h" |
7 | 7 |
|
8 | 8 | #include <gr_srv6.h> |
| 9 | +#include <gr_vrf.h> |
9 | 10 |
|
10 | 11 | #include <lib/srv6.h> |
| 12 | +#include <zebra/interface.h> |
11 | 13 | #include <zebra/rib.h> |
12 | 14 | #include <zebra/table_manager.h> |
13 | 15 | #include <zebra_dplane_grout.h> |
@@ -381,6 +383,90 @@ void grout_route6_change(bool new, struct gr_ip6_route *gr_r6) { |
381 | 383 | ); |
382 | 384 | } |
383 | 385 |
|
| 386 | +static enum zebra_dplane_result grout_add_del_vrf_route( |
| 387 | + struct zebra_dplane_ctx *ctx, |
| 388 | + const struct prefix *p, |
| 389 | + gr_nh_origin_t origin, |
| 390 | + struct nexthop *nh, |
| 391 | + vrf_id_t vrf_id, |
| 392 | + bool new |
| 393 | +) { |
| 394 | + union { |
| 395 | + struct gr_vrf_route_add_req rvrf_add; |
| 396 | + struct gr_vrf_route_del_req rvrf_del; |
| 397 | + } req; |
| 398 | + struct gr_vrf_route *vrf_route; |
| 399 | + struct gr_vrf_route_key *key; |
| 400 | + uint32_t req_type; |
| 401 | + size_t req_len; |
| 402 | + |
| 403 | + if (new) { |
| 404 | + req.rvrf_add = (struct gr_vrf_route_add_req) { |
| 405 | + .r.key.vrf_id = vrf_id, |
| 406 | + .exist_ok = true, |
| 407 | + .origin = origin, |
| 408 | + }; |
| 409 | + vrf_route = &req.rvrf_add.r; |
| 410 | + key = &vrf_route->key; |
| 411 | + req_type = GR_VRF_ROUTE_ADD; |
| 412 | + req_len = sizeof(struct gr_vrf_route_add_req); |
| 413 | + } else { |
| 414 | + req.rvrf_del = (struct gr_vrf_route_del_req) { |
| 415 | + .key.vrf_id = vrf_id, |
| 416 | + .missing_ok = false, |
| 417 | + }; |
| 418 | + vrf_route = NULL; |
| 419 | + key = &req.rvrf_del.key; |
| 420 | + req_type = GR_VRF_ROUTE_DEL; |
| 421 | + req_len = sizeof(struct gr_vrf_route_del_req); |
| 422 | + } |
| 423 | + *key = (struct gr_vrf_route_key) {.vrf_id = vrf_id, .is_dest6 = (p->family == AF_INET6)}; |
| 424 | + |
| 425 | + if (key->is_dest6) { |
| 426 | + memcpy(key->dest6.ip.a, p->u.prefix6.s6_addr, sizeof(key->dest6.ip.a)); |
| 427 | + key->dest6.prefixlen = p->prefixlen; |
| 428 | + |
| 429 | + gr_log_debug( |
| 430 | + "%s vrfroute %pI6/%u (origin %s) on vrf %u", |
| 431 | + new ? "add" : "del", |
| 432 | + &key->dest6.ip, |
| 433 | + key->dest6.prefixlen, |
| 434 | + gr_nh_origin_name(origin), |
| 435 | + vrf_id |
| 436 | + ); |
| 437 | + |
| 438 | + } else { |
| 439 | + key->dest4.ip = p->u.prefix4.s_addr; |
| 440 | + key->dest4.prefixlen = p->prefixlen; |
| 441 | + |
| 442 | + gr_log_debug( |
| 443 | + "%s vrf route %pI4/%u (origin %s) on vrf %u", |
| 444 | + new ? "add" : "del", |
| 445 | + &key->dest4.ip, |
| 446 | + key->dest4.prefixlen, |
| 447 | + gr_nh_origin_name(origin), |
| 448 | + vrf_id |
| 449 | + ); |
| 450 | + } |
| 451 | + |
| 452 | + // just need key to delete |
| 453 | + if (!new) |
| 454 | + goto end; |
| 455 | + |
| 456 | + vrf_route->out_vrf_id = nh->vrf_id; |
| 457 | + |
| 458 | +end: |
| 459 | + if (!is_selfroute(origin)) { |
| 460 | + gr_log_debug("no frr route, skip it"); |
| 461 | + return ZEBRA_DPLANE_REQUEST_SUCCESS; |
| 462 | + } |
| 463 | + |
| 464 | + if (grout_client_send_recv(req_type, req_len, &req, NULL) < 0) |
| 465 | + return ZEBRA_DPLANE_REQUEST_FAILURE; |
| 466 | + |
| 467 | + return ZEBRA_DPLANE_REQUEST_SUCCESS; |
| 468 | +} |
| 469 | + |
384 | 470 | static_assert(SRV6_MAX_SEGS <= GR_SRV6_ROUTE_SEGLIST_COUNT_MAX); |
385 | 471 |
|
386 | 472 | static enum zebra_dplane_result grout_add_del_srv6_route( |
@@ -662,7 +748,15 @@ enum zebra_dplane_result grout_add_del_route(struct zebra_dplane_ctx *ctx) { |
662 | 748 | gr_log_err("impossible to add/del srv6 route (invalid format)"); |
663 | 749 | return ZEBRA_DPLANE_REQUEST_FAILURE; |
664 | 750 | } |
| 751 | + if (nh && nh->type == NEXTHOP_TYPE_IFINDEX) { |
| 752 | + struct interface *ifp; |
| 753 | + |
| 754 | + ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(GROUT_NS), nh->ifindex); |
| 755 | + if (ifp && IS_ZEBRA_IF_VRF(ifp)) |
| 756 | + return grout_add_del_vrf_route(ctx, p, origin, nh, vrf_id, new); |
665 | 757 |
|
| 758 | + gr_log_err("impossible to add route with ifindex nexthop type"); |
| 759 | + } |
666 | 760 | if (new && nh_id == 0) { |
667 | 761 | gr_log_err("impossible to add route with no nexthop id"); |
668 | 762 | return ZEBRA_DPLANE_REQUEST_FAILURE; |
@@ -840,7 +934,17 @@ enum zebra_dplane_result grout_add_del_nexthop(struct zebra_dplane_ctx *ctx) { |
840 | 934 | gr_log_debug("add nexthop id %u gw %pI6", nh_id, &gr_nh->ipv6); |
841 | 935 | break; |
842 | 936 | case NEXTHOP_TYPE_IFINDEX: |
843 | | - gr_log_debug("add nexthop id %u ifindex %u", nh_id, gr_nh->iface_id); |
| 937 | + struct interface *ifp; |
| 938 | + |
| 939 | + ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(GROUT_NS), nh->ifindex); |
| 940 | + if (ifp && IS_ZEBRA_IF_VRF(ifp)) { |
| 941 | + gr_log_err( |
| 942 | + "impossible to add/del nexthop on vrf interface (not supported)" |
| 943 | + ); |
| 944 | + return ZEBRA_DPLANE_REQUEST_SUCCESS; |
| 945 | + } |
| 946 | + |
| 947 | + gr_log_err("impossible to add nexthop id %u ifindex %u", nh_id, gr_nh->iface_id); |
844 | 948 | return ZEBRA_DPLANE_REQUEST_FAILURE; |
845 | 949 | default: |
846 | 950 | gr_log_err("impossible to add nexthop %u (type %u not supported)", nh_id, nh->type); |
|
0 commit comments