extern int kernel_interface_set_master(struct interface *master,
struct interface *slave);
-extern enum zebra_dplane_result kernel_add_lsp(zebra_lsp_t *lsp);
-extern enum zebra_dplane_result kernel_upd_lsp(zebra_lsp_t *lsp);
-extern enum zebra_dplane_result kernel_del_lsp(zebra_lsp_t *lsp);
-
-/*
- * Add the ability to pass back up the lsp install/delete
- * success/failure.
- *
- * This functions goal is similiar to kernel_route_rib_pass_fail
- * in that we are separating out the mechanics for
- * the install/failure to set/unset flags and to notify
- * as needed.
- */
-extern void kernel_lsp_pass_fail(zebra_lsp_t *lsp, enum zebra_dplane_status res);
-
extern int mpls_kernel_init(void);
extern uint32_t kernel_get_speed(struct interface *ifp);
return netlink_neigh_update2(ifp, ip, NULL, 0, 0, RTM_DELNEIGH);
}
-/*
- * MPLS label forwarding table change via netlink interface.
- */
-int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp)
-{
- mpls_lse_t lse;
- zebra_nhlfe_t *nhlfe;
- struct nexthop *nexthop = NULL;
- unsigned int nexthop_num;
- const char *routedesc;
- struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
- int route_type;
-
- struct {
- struct nlmsghdr n;
- struct rtmsg r;
- char buf[NL_PKT_BUF_SIZE];
- } req;
-
- memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE);
-
- /*
- * Count # nexthops so we can decide whether to use singlepath
- * or multipath case.
- */
- nexthop_num = 0;
- for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
- nexthop = nhlfe->nexthop;
- if (!nexthop)
- continue;
- if (cmd == RTM_NEWROUTE) {
- /* Count all selected NHLFEs */
- if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
- && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- nexthop_num++;
- } else /* DEL */
- {
- /* Count all installed NHLFEs */
- if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)
- && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
- nexthop_num++;
- }
- }
-
- if ((nexthop_num == 0) || (!lsp->best_nhlfe && (cmd != RTM_DELROUTE)))
- return 0;
-
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
- req.n.nlmsg_type = cmd;
- req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
-
- req.r.rtm_family = AF_MPLS;
- req.r.rtm_table = RT_TABLE_MAIN;
- req.r.rtm_dst_len = MPLS_LABEL_LEN_BITS;
- req.r.rtm_scope = RT_SCOPE_UNIVERSE;
- req.r.rtm_type = RTN_UNICAST;
-
- if (cmd == RTM_NEWROUTE) {
- /* We do a replace to handle update. */
- req.n.nlmsg_flags |= NLM_F_REPLACE;
-
- /* set the protocol value if installing */
- route_type = re_type_from_lsp_type(lsp->best_nhlfe->type);
- req.r.rtm_protocol = zebra2proto(route_type);
- }
-
- /* Fill destination */
- lse = mpls_lse_encode(lsp->ile.in_label, 0, 0, 1);
- addattr_l(&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t));
-
- /* Fill nexthops (paths) based on single-path or multipath. The paths
- * chosen depend on the operation.
- */
- if (nexthop_num == 1) {
- routedesc = "single-path";
- _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
-
- nexthop_num = 0;
- for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
- nexthop = nhlfe->nexthop;
- if (!nexthop)
- continue;
-
- if ((cmd == RTM_NEWROUTE
- && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
- && CHECK_FLAG(nexthop->flags,
- NEXTHOP_FLAG_ACTIVE)))
- || (cmd == RTM_DELROUTE
- && (CHECK_FLAG(nhlfe->flags,
- NHLFE_FLAG_INSTALLED)
- && CHECK_FLAG(nexthop->flags,
- NEXTHOP_FLAG_FIB)))) {
- /* Add the gateway */
- _netlink_mpls_build_singlepath(routedesc, nhlfe,
- &req.n, &req.r,
- sizeof req, cmd);
- nexthop_num++;
- break;
- }
- }
- } else /* Multipath case */
- {
- char buf[NL_PKT_BUF_SIZE];
- struct rtattr *rta = (void *)buf;
- struct rtnexthop *rtnh;
- union g_addr *src1 = NULL;
-
- rta->rta_type = RTA_MULTIPATH;
- rta->rta_len = RTA_LENGTH(0);
- rtnh = RTA_DATA(rta);
-
- routedesc = "multipath";
- _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc);
-
- nexthop_num = 0;
- for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
- nexthop = nhlfe->nexthop;
- if (!nexthop)
- continue;
-
- if ((cmd == RTM_NEWROUTE
- && (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
- && CHECK_FLAG(nexthop->flags,
- NEXTHOP_FLAG_ACTIVE)))
- || (cmd == RTM_DELROUTE
- && (CHECK_FLAG(nhlfe->flags,
- NHLFE_FLAG_INSTALLED)
- && CHECK_FLAG(nexthop->flags,
- NEXTHOP_FLAG_FIB)))) {
- nexthop_num++;
-
- /* Build the multipath */
- _netlink_mpls_build_multipath(routedesc, nhlfe,
- rta, rtnh, &req.r,
- &src1);
- rtnh = RTNH_NEXT(rtnh);
- }
- }
-
- /* Add the multipath */
- if (rta->rta_len > RTA_LENGTH(0))
- addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_MULTIPATH,
- RTA_DATA(rta), RTA_PAYLOAD(rta));
- }
-
- /* Talk to netlink socket. */
- return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
- 0);
-}
-
/*
* MPLS label forwarding table change via netlink interface, using dataplane
* context information.
*/
-int netlink_mpls_multipath_ctx(int cmd, struct zebra_dplane_ctx *ctx)
+int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
{
mpls_lse_t lse;
zebra_nhlfe_t *nhlfe;
/* Fill nexthops (paths) based on single-path or multipath. The paths
* chosen depend on the operation.
*/
- if (nexthop_num == 1 || multipath_num == 1) {
+ if (nexthop_num == 1) {
routedesc = "single-path";
_netlink_mpls_debug(cmd, dplane_ctx_get_in_label(ctx),
routedesc);
if (!nexthop)
continue;
- if (nexthop_num >= multipath_num)
- break;
-
if ((cmd == RTM_NEWROUTE
&& (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
&& CHECK_FLAG(nexthop->flags,
void rt_netlink_init(void);
-extern int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp);
-
/* MPLS label forwarding table change, using dataplane context information. */
-extern int netlink_mpls_multipath_ctx(int cmd, struct zebra_dplane_ctx *ctx);
+extern int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx);
extern int netlink_route_change(struct nlmsghdr *h, ns_id_t ns_id, int startup);
extern int netlink_route_read(struct zebra_ns *zns);
/* Public functions */
-void kernel_lsp_pass_fail(zebra_lsp_t *lsp, enum zebra_dplane_status res)
-{
- struct nexthop *nexthop;
- zebra_nhlfe_t *nhlfe;
-
- if (!lsp)
- return;
-
- switch (res) {
- case ZEBRA_DPLANE_INSTALL_FAILURE:
- UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
- clear_nhlfe_installed(lsp);
- flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE,
- "LSP Install Failure: %u", lsp->ile.in_label);
- break;
- case ZEBRA_DPLANE_INSTALL_SUCCESS:
- SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
- for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
- nexthop = nhlfe->nexthop;
- if (!nexthop)
- continue;
-
- SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
- SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
- }
- break;
- case ZEBRA_DPLANE_DELETE_SUCCESS:
- UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
- clear_nhlfe_installed(lsp);
- break;
- case ZEBRA_DPLANE_DELETE_FAILURE:
- flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE,
- "LSP Deletion Failure: %u", lsp->ile.in_label);
- break;
- case ZEBRA_DPLANE_STATUS_NONE:
- break;
- }
-}
-
/*
* Process LSP update results from zebra dataplane.
*/
#include "zebra/rt_netlink.h"
#include "zebra/zebra_mpls.h"
-/*
- * Install Label Forwarding entry into the kernel.
- */
-enum zebra_dplane_result kernel_add_lsp(zebra_lsp_t *lsp)
-{
- int ret;
-
- if (!lsp || !lsp->best_nhlfe) { // unexpected
- kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_INSTALL_FAILURE);
- return ZEBRA_DPLANE_REQUEST_FAILURE;
- }
-
- ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp);
-
- kernel_lsp_pass_fail(lsp,
- (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS
- : ZEBRA_DPLANE_INSTALL_FAILURE);
-
- return ZEBRA_DPLANE_REQUEST_SUCCESS;
-}
-
-/*
- * Update Label Forwarding entry in the kernel. This means that the Label
- * forwarding entry is already installed and needs an update - either a new
- * path is to be added, an installed path has changed (e.g., outgoing label)
- * or an installed path (but not all paths) has to be removed. This performs
- * a REPLACE operation, internally.
- */
-enum zebra_dplane_result kernel_upd_lsp(zebra_lsp_t *lsp)
-{
- int ret;
-
- if (!lsp || !lsp->best_nhlfe) { // unexpected
- kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_INSTALL_FAILURE);
- return ZEBRA_DPLANE_REQUEST_FAILURE;
- }
-
- ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp);
-
- kernel_lsp_pass_fail(lsp,
- (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS
- : ZEBRA_DPLANE_INSTALL_FAILURE);
-
- return ZEBRA_DPLANE_REQUEST_SUCCESS;
-}
-
-/*
- * Delete Label Forwarding entry from the kernel.
- */
-enum zebra_dplane_result kernel_del_lsp(zebra_lsp_t *lsp)
-{
- int ret;
-
- if (!lsp) { // unexpected
- kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_DELETE_FAILURE);
- return ZEBRA_DPLANE_REQUEST_FAILURE;
- }
-
- if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) {
- kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_DELETE_FAILURE);
- return ZEBRA_DPLANE_REQUEST_FAILURE;
- }
-
- ret = netlink_mpls_multipath(RTM_DELROUTE, lsp);
-
- kernel_lsp_pass_fail(lsp,
- (!ret) ? ZEBRA_DPLANE_DELETE_SUCCESS
- : ZEBRA_DPLANE_DELETE_FAILURE);
-
- return ZEBRA_DPLANE_REQUEST_SUCCESS;
-}
-
/*
* LSP forwarding update using dataplane context information.
*/
/* Invalid op? */
goto done;
- ret = netlink_mpls_multipath_ctx(cmd, ctx);
+ ret = netlink_mpls_multipath(cmd, ctx);
done:
return ret;
}
-static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp)
+static int kernel_lsp_cmd(struct zebra_dplane_ctx *ctx)
{
zebra_nhlfe_t *nhlfe;
struct nexthop *nexthop = NULL;
unsigned int nexthop_num = 0;
+ int action;
- for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
+ switch (dplane_ctx_get_op(ctx)) {
+ case DPLANE_OP_LSP_DELETE:
+ action = RTM_DELETE;
+ break;
+ case DPLANE_OP_LSP_INSTALL:
+ action = RTM_ADD;
+ break;
+ case DPLANE_OP_LSP_UPDATE:
+ action = RTM_CHANGE;
+ break;
+ default:
+ return -1;
+ }
+
+ for (nhlfe = dplane_ctx_get_nhlfe(ctx); nhlfe; nhlfe = nhlfe->next) {
nexthop = nhlfe->nexthop;
if (!nexthop)
continue;
switch (NHLFE_FAMILY(nhlfe)) {
case AF_INET:
- kernel_send_rtmsg_v4(action, lsp->ile.in_label,
- nhlfe);
+ kernel_send_rtmsg_v4(
+ action,
+ dplane_ctx_get_in_label(ctx),
+ nhlfe);
break;
case AF_INET6:
- kernel_send_rtmsg_v6(action, lsp->ile.in_label,
- nhlfe);
+ kernel_send_rtmsg_v6(
+ action,
+ dplane_ctx_get_in_label(ctx),
+ nhlfe);
break;
default:
break;
return (0);
}
-enum zebra_dplane_result kernel_add_lsp(zebra_lsp_t *lsp)
-{
- int ret;
-
- if (!lsp || !lsp->best_nhlfe) { // unexpected
- kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_INSTALL_FAILURE);
- return ZEBRA_DPLANE_REQUEST_FAILURE;
- }
-
- ret = kernel_lsp_cmd(RTM_ADD, lsp);
-
- kernel_lsp_pass_fail(lsp,
- (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS
- : ZEBRA_DPLANE_INSTALL_FAILURE);
-
- return ZEBRA_DPLANE_REQUEST_SUCCESS;
-}
-
-enum zebra_dplane_result kernel_upd_lsp(zebra_lsp_t *lsp)
-{
- int ret;
-
- if (!lsp || !lsp->best_nhlfe) { // unexpected
- kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_INSTALL_FAILURE);
- return ZEBRA_DPLANE_REQUEST_FAILURE;
- }
-
- ret = kernel_lsp_cmd(RTM_CHANGE, lsp);
-
- kernel_lsp_pass_fail(lsp,
- (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS
- : ZEBRA_DPLANE_INSTALL_FAILURE);
- return ZEBRA_DPLANE_REQUEST_SUCCESS;
-}
-
-enum zebra_dplane_result kernel_del_lsp(zebra_lsp_t *lsp)
+enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx)
{
int ret;
- if (!lsp) { // unexpected
- kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_DELETE_FAILURE);
- return ZEBRA_DPLANE_REQUEST_FAILURE;
- }
+ ret = kernel_lsp_cmd(ctx);
- if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) {
- kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_DELETE_FAILURE);
- return ZEBRA_DPLANE_REQUEST_FAILURE;
- }
-
- ret = kernel_lsp_cmd(RTM_DELETE, lsp);
-
- kernel_lsp_pass_fail(lsp,
- (!ret) ? ZEBRA_DPLANE_DELETE_SUCCESS
- : ZEBRA_DPLANE_DELETE_FAILURE);
-
- return ZEBRA_DPLANE_REQUEST_SUCCESS;
-}
-
-enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx)
-{
- return ZEBRA_DPLANE_REQUEST_FAILURE;
+ return (ret == 0 ?
+ ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
}
static int kmpw_install(struct zebra_pw *pw)