mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 22:29:23 +00:00
Merge pull request #3684 from mjstapp/dplane_pw
zebra: async dataplane for pseudowires
This commit is contained in:
commit
4634d02cfd
@ -32,7 +32,7 @@
|
|||||||
#include "zebra/zebra_dplane.h"
|
#include "zebra/zebra_dplane.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update or delete a route or LSP from the kernel,
|
* Update or delete a route, LSP, or pseudowire from the kernel,
|
||||||
* using info from a dataplane context.
|
* using info from a dataplane context.
|
||||||
*/
|
*/
|
||||||
extern enum zebra_dplane_result kernel_route_update(
|
extern enum zebra_dplane_result kernel_route_update(
|
||||||
@ -41,6 +41,8 @@ extern enum zebra_dplane_result kernel_route_update(
|
|||||||
extern enum zebra_dplane_result kernel_lsp_update(
|
extern enum zebra_dplane_result kernel_lsp_update(
|
||||||
struct zebra_dplane_ctx *ctx);
|
struct zebra_dplane_ctx *ctx);
|
||||||
|
|
||||||
|
enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx);
|
||||||
|
|
||||||
extern int kernel_address_add_ipv4(struct interface *, struct connected *);
|
extern int kernel_address_add_ipv4(struct interface *, struct connected *);
|
||||||
extern int kernel_address_delete_ipv4(struct interface *, struct connected *);
|
extern int kernel_address_delete_ipv4(struct interface *, struct connected *);
|
||||||
extern int kernel_address_add_ipv6(struct interface *, struct connected *);
|
extern int kernel_address_add_ipv6(struct interface *, struct connected *);
|
||||||
|
@ -101,6 +101,23 @@ struct dplane_route_info {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pseudowire info for the dataplane
|
||||||
|
*/
|
||||||
|
struct dplane_pw_info {
|
||||||
|
char ifname[IF_NAMESIZE];
|
||||||
|
ifindex_t ifindex;
|
||||||
|
int type;
|
||||||
|
int af;
|
||||||
|
int status;
|
||||||
|
uint32_t flags;
|
||||||
|
union g_addr nexthop;
|
||||||
|
mpls_label_t local_label;
|
||||||
|
mpls_label_t remote_label;
|
||||||
|
|
||||||
|
union pw_protocol_fields fields;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The context block used to exchange info about route updates across
|
* The context block used to exchange info about route updates across
|
||||||
* the boundary between the zebra main context (and pthread) and the
|
* the boundary between the zebra main context (and pthread) and the
|
||||||
@ -136,6 +153,7 @@ struct zebra_dplane_ctx {
|
|||||||
union {
|
union {
|
||||||
struct dplane_route_info rinfo;
|
struct dplane_route_info rinfo;
|
||||||
zebra_lsp_t lsp;
|
zebra_lsp_t lsp;
|
||||||
|
struct dplane_pw_info pw;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
/* Namespace info, used especially for netlink kernel communication */
|
/* Namespace info, used especially for netlink kernel communication */
|
||||||
@ -237,10 +255,11 @@ static struct zebra_dplane_globals {
|
|||||||
_Atomic uint32_t dg_other_errors;
|
_Atomic uint32_t dg_other_errors;
|
||||||
|
|
||||||
_Atomic uint32_t dg_lsps_in;
|
_Atomic uint32_t dg_lsps_in;
|
||||||
_Atomic uint32_t dg_lsps_queued;
|
|
||||||
_Atomic uint32_t dg_lsps_queued_max;
|
|
||||||
_Atomic uint32_t dg_lsp_errors;
|
_Atomic uint32_t dg_lsp_errors;
|
||||||
|
|
||||||
|
_Atomic uint32_t dg_pws_in;
|
||||||
|
_Atomic uint32_t dg_pw_errors;
|
||||||
|
|
||||||
_Atomic uint32_t dg_update_yields;
|
_Atomic uint32_t dg_update_yields;
|
||||||
|
|
||||||
/* Dataplane pthread */
|
/* Dataplane pthread */
|
||||||
@ -276,6 +295,8 @@ static void dplane_info_from_zns(struct zebra_dplane_info *ns_info,
|
|||||||
struct zebra_ns *zns);
|
struct zebra_ns *zns);
|
||||||
static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp,
|
static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp,
|
||||||
enum dplane_op_e op);
|
enum dplane_op_e op);
|
||||||
|
static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
|
||||||
|
enum dplane_op_e op);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Public APIs
|
* Public APIs
|
||||||
@ -363,6 +384,8 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DPLANE_OP_PW_INSTALL:
|
||||||
|
case DPLANE_OP_PW_UNINSTALL:
|
||||||
case DPLANE_OP_NONE:
|
case DPLANE_OP_NONE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -490,6 +513,13 @@ const char *dplane_op2str(enum dplane_op_e op)
|
|||||||
ret = "LSP_DELETE";
|
ret = "LSP_DELETE";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DPLANE_OP_PW_INSTALL:
|
||||||
|
ret = "PW_INSTALL";
|
||||||
|
break;
|
||||||
|
case DPLANE_OP_PW_UNINSTALL:
|
||||||
|
ret = "PW_UNINSTALL";
|
||||||
|
break;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -735,6 +765,71 @@ uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx)
|
|||||||
return ctx->u.lsp.num_ecmp;
|
return ctx->u.lsp.num_ecmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *dplane_ctx_get_pw_ifname(const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
|
||||||
|
return ctx->u.pw.ifname;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
|
||||||
|
return ctx->u.pw.local_label;
|
||||||
|
}
|
||||||
|
|
||||||
|
mpls_label_t dplane_ctx_get_pw_remote_label(const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
|
||||||
|
return ctx->u.pw.remote_label;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dplane_ctx_get_pw_type(const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
|
||||||
|
return ctx->u.pw.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dplane_ctx_get_pw_af(const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
|
||||||
|
return ctx->u.pw.af;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t dplane_ctx_get_pw_flags(const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
|
||||||
|
return ctx->u.pw.flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dplane_ctx_get_pw_status(const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
|
||||||
|
return ctx->u.pw.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
const union g_addr *dplane_ctx_get_pw_nexthop(
|
||||||
|
const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
|
||||||
|
return &(ctx->u.pw.nexthop);
|
||||||
|
}
|
||||||
|
|
||||||
|
const union pw_protocol_fields *dplane_ctx_get_pw_proto(
|
||||||
|
const struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
DPLANE_CTX_VALID(ctx);
|
||||||
|
|
||||||
|
return &(ctx->u.pw.fields);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* End of dplane context accessors
|
* End of dplane context accessors
|
||||||
*/
|
*/
|
||||||
@ -937,6 +1032,47 @@ static int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Capture information for an LSP update in a dplane context.
|
||||||
|
*/
|
||||||
|
static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
|
||||||
|
enum dplane_op_e op,
|
||||||
|
struct zebra_pw *pw)
|
||||||
|
{
|
||||||
|
int ret = AOK;
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
|
||||||
|
zlog_debug("init dplane ctx %s: pw '%s', loc %u, rem %u",
|
||||||
|
dplane_op2str(op), pw->ifname, pw->local_label,
|
||||||
|
pw->remote_label);
|
||||||
|
|
||||||
|
ctx->zd_op = op;
|
||||||
|
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
|
||||||
|
|
||||||
|
/* Capture namespace info: no netlink support as of 12/18,
|
||||||
|
* but just in case...
|
||||||
|
*/
|
||||||
|
dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), false);
|
||||||
|
|
||||||
|
memset(&ctx->u.pw, 0, sizeof(ctx->u.pw));
|
||||||
|
|
||||||
|
/* This name appears to be c-string, so we use string copy. */
|
||||||
|
strlcpy(ctx->u.pw.ifname, pw->ifname, sizeof(ctx->u.pw.ifname));
|
||||||
|
ctx->zd_vrf_id = pw->vrf_id;
|
||||||
|
ctx->u.pw.ifindex = pw->ifindex;
|
||||||
|
ctx->u.pw.type = pw->type;
|
||||||
|
ctx->u.pw.af = pw->af;
|
||||||
|
ctx->u.pw.local_label = pw->local_label;
|
||||||
|
ctx->u.pw.remote_label = pw->remote_label;
|
||||||
|
ctx->u.pw.flags = pw->flags;
|
||||||
|
|
||||||
|
ctx->u.pw.nexthop = pw->nexthop;
|
||||||
|
|
||||||
|
ctx->u.pw.fields = pw->data;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enqueue a new route update,
|
* Enqueue a new route update,
|
||||||
* and ensure an event is active for the dataplane pthread.
|
* and ensure an event is active for the dataplane pthread.
|
||||||
@ -1140,6 +1276,22 @@ enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enqueue pseudowire install for the dataplane.
|
||||||
|
*/
|
||||||
|
enum zebra_dplane_result dplane_pw_install(struct zebra_pw *pw)
|
||||||
|
{
|
||||||
|
return pw_update_internal(pw, DPLANE_OP_PW_INSTALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enqueue pseudowire un-install for the dataplane.
|
||||||
|
*/
|
||||||
|
enum zebra_dplane_result dplane_pw_uninstall(struct zebra_pw *pw)
|
||||||
|
{
|
||||||
|
return pw_update_internal(pw, DPLANE_OP_PW_UNINSTALL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Common internal LSP update utility
|
* Common internal LSP update utility
|
||||||
*/
|
*/
|
||||||
@ -1180,6 +1332,45 @@ done:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal, common handler for pseudowire updates.
|
||||||
|
*/
|
||||||
|
static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
|
||||||
|
enum dplane_op_e op)
|
||||||
|
{
|
||||||
|
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||||
|
int ret;
|
||||||
|
struct zebra_dplane_ctx *ctx = NULL;
|
||||||
|
|
||||||
|
ctx = dplane_ctx_alloc();
|
||||||
|
if (ctx == NULL) {
|
||||||
|
ret = ENOMEM;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = dplane_ctx_pw_init(ctx, op, pw);
|
||||||
|
if (ret != AOK)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
ret = dplane_route_enqueue(ctx);
|
||||||
|
|
||||||
|
done:
|
||||||
|
/* Update counter */
|
||||||
|
atomic_fetch_add_explicit(&zdplane_info.dg_pws_in, 1,
|
||||||
|
memory_order_relaxed);
|
||||||
|
|
||||||
|
if (ret == AOK)
|
||||||
|
result = ZEBRA_DPLANE_REQUEST_QUEUED;
|
||||||
|
else {
|
||||||
|
atomic_fetch_add_explicit(&zdplane_info.dg_pw_errors, 1,
|
||||||
|
memory_order_relaxed);
|
||||||
|
if (ctx)
|
||||||
|
dplane_ctx_free(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handler for 'show dplane'
|
* Handler for 'show dplane'
|
||||||
*/
|
*/
|
||||||
@ -1511,6 +1702,32 @@ kernel_dplane_lsp_update(struct zebra_dplane_ctx *ctx)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler for kernel pseudowire updates
|
||||||
|
*/
|
||||||
|
static enum zebra_dplane_result
|
||||||
|
kernel_dplane_pw_update(struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
enum zebra_dplane_result res;
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
|
||||||
|
zlog_debug("Dplane pw %s: op %s af %d loc: %u rem: %u",
|
||||||
|
dplane_ctx_get_pw_ifname(ctx),
|
||||||
|
dplane_op2str(ctx->zd_op),
|
||||||
|
dplane_ctx_get_pw_af(ctx),
|
||||||
|
dplane_ctx_get_pw_local_label(ctx),
|
||||||
|
dplane_ctx_get_pw_remote_label(ctx));
|
||||||
|
|
||||||
|
res = kernel_pw_update(ctx);
|
||||||
|
|
||||||
|
if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
|
||||||
|
atomic_fetch_add_explicit(
|
||||||
|
&zdplane_info.dg_pw_errors, 1,
|
||||||
|
memory_order_relaxed);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handler for kernel route updates
|
* Handler for kernel route updates
|
||||||
*/
|
*/
|
||||||
@ -1577,6 +1794,11 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
|
|||||||
res = kernel_dplane_lsp_update(ctx);
|
res = kernel_dplane_lsp_update(ctx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DPLANE_OP_PW_INSTALL:
|
||||||
|
case DPLANE_OP_PW_UNINSTALL:
|
||||||
|
res = kernel_dplane_pw_update(ctx);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
atomic_fetch_add_explicit(
|
atomic_fetch_add_explicit(
|
||||||
&zdplane_info.dg_other_errors, 1,
|
&zdplane_info.dg_other_errors, 1,
|
||||||
|
@ -105,7 +105,11 @@ enum dplane_op_e {
|
|||||||
/* LSP update */
|
/* LSP update */
|
||||||
DPLANE_OP_LSP_INSTALL,
|
DPLANE_OP_LSP_INSTALL,
|
||||||
DPLANE_OP_LSP_UPDATE,
|
DPLANE_OP_LSP_UPDATE,
|
||||||
DPLANE_OP_LSP_DELETE
|
DPLANE_OP_LSP_DELETE,
|
||||||
|
|
||||||
|
/* Pseudowire update */
|
||||||
|
DPLANE_OP_PW_INSTALL,
|
||||||
|
DPLANE_OP_PW_UNINSTALL,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -203,6 +207,19 @@ zebra_nhlfe_t *dplane_ctx_get_nhlfe(struct zebra_dplane_ctx *ctx);
|
|||||||
zebra_nhlfe_t *dplane_ctx_get_best_nhlfe(struct zebra_dplane_ctx *ctx);
|
zebra_nhlfe_t *dplane_ctx_get_best_nhlfe(struct zebra_dplane_ctx *ctx);
|
||||||
uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx);
|
uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx);
|
||||||
|
|
||||||
|
/* Accessors for pseudowire information */
|
||||||
|
const char *dplane_ctx_get_pw_ifname(const struct zebra_dplane_ctx *ctx);
|
||||||
|
mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx);
|
||||||
|
mpls_label_t dplane_ctx_get_pw_remote_label(const struct zebra_dplane_ctx *ctx);
|
||||||
|
int dplane_ctx_get_pw_type(const struct zebra_dplane_ctx *ctx);
|
||||||
|
int dplane_ctx_get_pw_af(const struct zebra_dplane_ctx *ctx);
|
||||||
|
uint32_t dplane_ctx_get_pw_flags(const struct zebra_dplane_ctx *ctx);
|
||||||
|
int dplane_ctx_get_pw_status(const struct zebra_dplane_ctx *ctx);
|
||||||
|
const union g_addr *dplane_ctx_get_pw_nexthop(
|
||||||
|
const struct zebra_dplane_ctx *ctx);
|
||||||
|
const union pw_protocol_fields *dplane_ctx_get_pw_proto(
|
||||||
|
const struct zebra_dplane_ctx *ctx);
|
||||||
|
|
||||||
/* Namespace info - esp. for netlink communication */
|
/* Namespace info - esp. for netlink communication */
|
||||||
const struct zebra_dplane_info *dplane_ctx_get_ns(
|
const struct zebra_dplane_info *dplane_ctx_get_ns(
|
||||||
const struct zebra_dplane_ctx *ctx);
|
const struct zebra_dplane_ctx *ctx);
|
||||||
@ -232,6 +249,12 @@ enum zebra_dplane_result dplane_lsp_add(zebra_lsp_t *lsp);
|
|||||||
enum zebra_dplane_result dplane_lsp_update(zebra_lsp_t *lsp);
|
enum zebra_dplane_result dplane_lsp_update(zebra_lsp_t *lsp);
|
||||||
enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp);
|
enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enqueue pseudowire operations for the dataplane.
|
||||||
|
*/
|
||||||
|
enum zebra_dplane_result dplane_pw_install(struct zebra_pw *pw);
|
||||||
|
enum zebra_dplane_result dplane_pw_uninstall(struct zebra_pw *pw);
|
||||||
|
|
||||||
/* Retrieve the limit on the number of pending, unprocessed updates. */
|
/* Retrieve the limit on the number of pending, unprocessed updates. */
|
||||||
uint32_t dplane_get_in_queue_limit(void);
|
uint32_t dplane_get_in_queue_limit(void);
|
||||||
|
|
||||||
|
@ -61,6 +61,16 @@ done:
|
|||||||
ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
|
ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pseudowire update api - not supported by netlink as of 12/18,
|
||||||
|
* but note that the default has been to report 'success' for pw updates
|
||||||
|
* on unsupported platforms.
|
||||||
|
*/
|
||||||
|
enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
return ZEBRA_DPLANE_REQUEST_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
int mpls_kernel_init(void)
|
int mpls_kernel_init(void)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
@ -29,6 +29,15 @@ int mpls_kernel_init(void)
|
|||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pseudowire update api - note that the default has been
|
||||||
|
* to report 'success' for pw updates on unsupported platforms.
|
||||||
|
*/
|
||||||
|
enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
return ZEBRA_DPLANE_REQUEST_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx)
|
enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx)
|
||||||
{
|
{
|
||||||
return ZEBRA_DPLANE_REQUEST_FAILURE;
|
return ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||||
|
@ -314,16 +314,17 @@ enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx)
|
|||||||
ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
|
ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kmpw_install(struct zebra_pw *pw)
|
static enum zebra_dplane_result kmpw_install(struct zebra_dplane_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
struct ifmpwreq imr;
|
struct ifmpwreq imr;
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss;
|
struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss;
|
||||||
struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss;
|
struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss;
|
||||||
|
const union g_addr *gaddr;
|
||||||
|
|
||||||
memset(&imr, 0, sizeof(imr));
|
memset(&imr, 0, sizeof(imr));
|
||||||
switch (pw->type) {
|
switch (dplane_ctx_get_pw_type(ctx)) {
|
||||||
case PW_TYPE_ETHERNET:
|
case PW_TYPE_ETHERNET:
|
||||||
imr.imr_type = IMR_TYPE_ETHERNET;
|
imr.imr_type = IMR_TYPE_ETHERNET;
|
||||||
break;
|
break;
|
||||||
@ -332,67 +333,91 @@ static int kmpw_install(struct zebra_pw *pw)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
zlog_debug("%s: unhandled pseudowire type (%#X)", __func__,
|
zlog_debug("%s: unhandled pseudowire type (%#X)", __func__,
|
||||||
pw->type);
|
dplane_ctx_get_pw_type(ctx));
|
||||||
return -1;
|
return ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pw->flags & F_PSEUDOWIRE_CWORD)
|
if (dplane_ctx_get_pw_flags(ctx) & F_PSEUDOWIRE_CWORD)
|
||||||
imr.imr_flags |= IMR_FLAG_CONTROLWORD;
|
imr.imr_flags |= IMR_FLAG_CONTROLWORD;
|
||||||
|
|
||||||
/* pseudowire nexthop */
|
/* pseudowire nexthop */
|
||||||
memset(&ss, 0, sizeof(ss));
|
memset(&ss, 0, sizeof(ss));
|
||||||
switch (pw->af) {
|
gaddr = dplane_ctx_get_pw_nexthop(ctx);
|
||||||
|
switch (dplane_ctx_get_pw_af(ctx)) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
sa_in->sin_family = AF_INET;
|
sa_in->sin_family = AF_INET;
|
||||||
sa_in->sin_len = sizeof(struct sockaddr_in);
|
sa_in->sin_len = sizeof(struct sockaddr_in);
|
||||||
sa_in->sin_addr = pw->nexthop.ipv4;
|
sa_in->sin_addr = gaddr->ipv4;
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
sa_in6->sin6_family = AF_INET6;
|
sa_in6->sin6_family = AF_INET6;
|
||||||
sa_in6->sin6_len = sizeof(struct sockaddr_in6);
|
sa_in6->sin6_len = sizeof(struct sockaddr_in6);
|
||||||
sa_in6->sin6_addr = pw->nexthop.ipv6;
|
sa_in6->sin6_addr = gaddr->ipv6;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
zlog_debug("%s: unhandled pseudowire address-family (%u)",
|
zlog_debug("%s: unhandled pseudowire address-family (%u)",
|
||||||
__func__, pw->af);
|
__func__, dplane_ctx_get_pw_af(ctx));
|
||||||
return -1;
|
return ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||||
}
|
}
|
||||||
memcpy(&imr.imr_nexthop, (struct sockaddr *)&ss,
|
memcpy(&imr.imr_nexthop, (struct sockaddr *)&ss,
|
||||||
sizeof(imr.imr_nexthop));
|
sizeof(imr.imr_nexthop));
|
||||||
|
|
||||||
/* pseudowire local/remote labels */
|
/* pseudowire local/remote labels */
|
||||||
imr.imr_lshim.shim_label = pw->local_label;
|
imr.imr_lshim.shim_label = dplane_ctx_get_pw_local_label(ctx);
|
||||||
imr.imr_rshim.shim_label = pw->remote_label;
|
imr.imr_rshim.shim_label = dplane_ctx_get_pw_remote_label(ctx);
|
||||||
|
|
||||||
/* ioctl */
|
/* ioctl */
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
strlcpy(ifr.ifr_name, pw->ifname, sizeof(ifr.ifr_name));
|
strlcpy(ifr.ifr_name, dplane_ctx_get_pw_ifname(ctx),
|
||||||
|
sizeof(ifr.ifr_name));
|
||||||
ifr.ifr_data = (caddr_t)&imr;
|
ifr.ifr_data = (caddr_t)&imr;
|
||||||
if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
|
if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
|
||||||
flog_err_sys(EC_LIB_SYSTEM_CALL, "ioctl SIOCSETMPWCFG: %s",
|
flog_err_sys(EC_LIB_SYSTEM_CALL, "ioctl SIOCSETMPWCFG: %s",
|
||||||
safe_strerror(errno));
|
safe_strerror(errno));
|
||||||
return -1;
|
return ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return ZEBRA_DPLANE_REQUEST_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kmpw_uninstall(struct zebra_pw *pw)
|
static enum zebra_dplane_result kmpw_uninstall(struct zebra_dplane_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
struct ifmpwreq imr;
|
struct ifmpwreq imr;
|
||||||
|
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
memset(&imr, 0, sizeof(imr));
|
memset(&imr, 0, sizeof(imr));
|
||||||
strlcpy(ifr.ifr_name, pw->ifname, sizeof(ifr.ifr_name));
|
strlcpy(ifr.ifr_name, dplane_ctx_get_pw_ifname(ctx),
|
||||||
|
sizeof(ifr.ifr_name));
|
||||||
ifr.ifr_data = (caddr_t)&imr;
|
ifr.ifr_data = (caddr_t)&imr;
|
||||||
if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
|
if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
|
||||||
flog_err_sys(EC_LIB_SYSTEM_CALL, "ioctl SIOCSETMPWCFG: %s",
|
flog_err_sys(EC_LIB_SYSTEM_CALL, "ioctl SIOCSETMPWCFG: %s",
|
||||||
safe_strerror(errno));
|
safe_strerror(errno));
|
||||||
return -1;
|
return ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return ZEBRA_DPLANE_REQUEST_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pseudowire update api for openbsd.
|
||||||
|
*/
|
||||||
|
enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||||
|
|
||||||
|
switch (dplane_ctx_get_op(ctx)) {
|
||||||
|
case DPLANE_OP_PW_INSTALL:
|
||||||
|
result = kmpw_install(ctx);
|
||||||
|
break;
|
||||||
|
case DPLANE_OP_PW_UNINSTALL:
|
||||||
|
result = kmpw_uninstall(ctx);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_RTSOCK_BUF 128 * 1024
|
#define MAX_RTSOCK_BUF 128 * 1024
|
||||||
@ -431,10 +456,6 @@ int mpls_kernel_init(void)
|
|||||||
|
|
||||||
kr_state.rtseq = 1;
|
kr_state.rtseq = 1;
|
||||||
|
|
||||||
/* register hook to install/uninstall pseudowires */
|
|
||||||
hook_register(pw_install, kmpw_install);
|
|
||||||
hook_register(pw_uninstall, kmpw_uninstall);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,9 +96,10 @@ void zebra_pw_del(struct zebra_vrf *zvrf, struct zebra_pw *pw)
|
|||||||
zebra_deregister_rnh_pseudowire(pw->vrf_id, pw);
|
zebra_deregister_rnh_pseudowire(pw->vrf_id, pw);
|
||||||
|
|
||||||
/* uninstall */
|
/* uninstall */
|
||||||
if (pw->status == PW_STATUS_UP)
|
if (pw->status == PW_STATUS_UP) {
|
||||||
hook_call(pw_uninstall, pw);
|
hook_call(pw_uninstall, pw);
|
||||||
else if (pw->install_retry_timer)
|
dplane_pw_uninstall(pw);
|
||||||
|
} else if (pw->install_retry_timer)
|
||||||
THREAD_TIMER_OFF(pw->install_retry_timer);
|
THREAD_TIMER_OFF(pw->install_retry_timer);
|
||||||
|
|
||||||
/* unlink and release memory */
|
/* unlink and release memory */
|
||||||
@ -169,7 +170,8 @@ static void zebra_pw_install(struct zebra_pw *pw)
|
|||||||
pw->vrf_id, pw->ifname,
|
pw->vrf_id, pw->ifname,
|
||||||
zebra_route_string(pw->protocol));
|
zebra_route_string(pw->protocol));
|
||||||
|
|
||||||
if (hook_call(pw_install, pw)) {
|
hook_call(pw_install, pw);
|
||||||
|
if (dplane_pw_install(pw) == ZEBRA_DPLANE_REQUEST_FAILURE) {
|
||||||
zebra_pw_install_failure(pw);
|
zebra_pw_install_failure(pw);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -190,6 +192,7 @@ static void zebra_pw_uninstall(struct zebra_pw *pw)
|
|||||||
|
|
||||||
/* ignore any possible error */
|
/* ignore any possible error */
|
||||||
hook_call(pw_uninstall, pw);
|
hook_call(pw_uninstall, pw);
|
||||||
|
dplane_pw_uninstall(pw);
|
||||||
|
|
||||||
if (zebra_pw_enabled(pw))
|
if (zebra_pw_enabled(pw))
|
||||||
zebra_pw_update_status(pw, PW_STATUS_DOWN);
|
zebra_pw_update_status(pw, PW_STATUS_DOWN);
|
||||||
|
@ -62,8 +62,8 @@ RB_PROTOTYPE(zebra_static_pw_head, zebra_pw, static_pw_entry, zebra_pw_compare);
|
|||||||
DECLARE_HOOK(pw_install, (struct zebra_pw * pw), (pw))
|
DECLARE_HOOK(pw_install, (struct zebra_pw * pw), (pw))
|
||||||
DECLARE_HOOK(pw_uninstall, (struct zebra_pw * pw), (pw))
|
DECLARE_HOOK(pw_uninstall, (struct zebra_pw * pw), (pw))
|
||||||
|
|
||||||
struct zebra_pw *zebra_pw_add(struct zebra_vrf *, const char *, uint8_t,
|
struct zebra_pw *zebra_pw_add(struct zebra_vrf *zvrf, const char *ifname,
|
||||||
struct zserv *);
|
uint8_t protocol, struct zserv *client);
|
||||||
void zebra_pw_del(struct zebra_vrf *, struct zebra_pw *);
|
void zebra_pw_del(struct zebra_vrf *, struct zebra_pw *);
|
||||||
void zebra_pw_change(struct zebra_pw *, ifindex_t, int, int, union g_addr *,
|
void zebra_pw_change(struct zebra_pw *, ifindex_t, int, int, union g_addr *,
|
||||||
uint32_t, uint32_t, uint8_t, union pw_protocol_fields *);
|
uint32_t, uint32_t, uint8_t, union pw_protocol_fields *);
|
||||||
|
@ -3225,6 +3225,34 @@ void rib_close_table(struct route_table *table)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler for async dataplane results after a pseudowire installation
|
||||||
|
*/
|
||||||
|
static int handle_pw_result(struct zebra_dplane_ctx *ctx)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct zebra_pw *pw;
|
||||||
|
struct zebra_vrf *vrf;
|
||||||
|
|
||||||
|
/* The pseudowire code assumes success - we act on an error
|
||||||
|
* result for installation attempts here.
|
||||||
|
*/
|
||||||
|
if (dplane_ctx_get_op(ctx) != DPLANE_OP_PW_INSTALL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (dplane_ctx_get_status(ctx) != ZEBRA_DPLANE_REQUEST_SUCCESS) {
|
||||||
|
vrf = zebra_vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
|
||||||
|
pw = zebra_pw_find(vrf, dplane_ctx_get_pw_ifname(ctx));
|
||||||
|
if (pw)
|
||||||
|
zebra_pw_install_failure(pw);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle results from the dataplane system. Dequeue update context
|
* Handle results from the dataplane system. Dequeue update context
|
||||||
* structs, dispatch to appropriate internal handlers.
|
* structs, dispatch to appropriate internal handlers.
|
||||||
@ -3236,8 +3264,6 @@ static int rib_process_dplane_results(struct thread *thread)
|
|||||||
|
|
||||||
/* Dequeue a list of completed updates with one lock/unlock cycle */
|
/* Dequeue a list of completed updates with one lock/unlock cycle */
|
||||||
|
|
||||||
/* TODO -- dequeue a list with one lock/unlock cycle? */
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
TAILQ_INIT(&ctxlist);
|
TAILQ_INIT(&ctxlist);
|
||||||
|
|
||||||
@ -3270,6 +3296,11 @@ static int rib_process_dplane_results(struct thread *thread)
|
|||||||
zebra_mpls_lsp_dplane_result(ctx);
|
zebra_mpls_lsp_dplane_result(ctx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DPLANE_OP_PW_INSTALL:
|
||||||
|
case DPLANE_OP_PW_UNINSTALL:
|
||||||
|
handle_pw_result(ctx);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Don't expect this: just return the struct? */
|
/* Don't expect this: just return the struct? */
|
||||||
dplane_ctx_fini(&ctx);
|
dplane_ctx_fini(&ctx);
|
||||||
|
Loading…
Reference in New Issue
Block a user