diff options
| author | Philippe Guibert <philippe.guibert@6wind.com> | 2021-03-11 15:33:41 +0100 | 
|---|---|---|
| committer | Philippe Guibert <philippe.guibert@6wind.com> | 2021-04-30 10:33:18 +0200 | 
| commit | 62b4b7e44ae72cbd611a78cd7abe8558366af21c (patch) | |
| tree | 254284fcdf2a9c7d4fca1c19d8645fafe2222c03 /zebra | |
| parent | 372b887859b7e5739137b02a1cecf2ea702ba586 (diff) | |
zebra: new dplane action to set gre link interface
This action is initiated by nhrp and has been stubbed when
moving to zebra. Now, a netlink request is forged to set
the link interface of a gre interface if that gre interface
does not have already a link interface.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/if_netlink.c | 60 | ||||
| -rw-r--r-- | zebra/if_netlink.h | 3 | ||||
| -rw-r--r-- | zebra/kernel_netlink.c | 3 | ||||
| -rw-r--r-- | zebra/rt.h | 3 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 8 | ||||
| -rw-r--r-- | zebra/rt_socket.c | 6 | ||||
| -rw-r--r-- | zebra/zapi_msg.c | 24 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 103 | ||||
| -rw-r--r-- | zebra/zebra_dplane.h | 11 | ||||
| -rw-r--r-- | zebra/zebra_errors.h | 1 | ||||
| -rw-r--r-- | zebra/zebra_nhg.c | 1 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 1 | 
12 files changed, 203 insertions, 21 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index bc74babd19..44ee8d9469 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -463,6 +463,46 @@ uint32_t kernel_get_speed(struct interface *ifp, int *error)  	return get_iflink_speed(ifp, error);  } +static ssize_t +netlink_gre_set_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf, +			    size_t buflen) +{ +	struct { +		struct nlmsghdr n; +		struct ifinfomsg ifi; +		char buf[]; +	} *req = buf; +	uint32_t link_idx; +	struct rtattr *rta_info, *rta_data; + +	if (buflen < sizeof(*req)) +		return 0; +	memset(req, 0, sizeof(*req)); + +	req->n.nlmsg_type =  RTM_NEWLINK; +	req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); +	req->n.nlmsg_flags = NLM_F_REQUEST; + +	req->ifi.ifi_index = dplane_ctx_get_ifindex(ctx); +	req->ifi.ifi_change = 0xFFFFFFFF; +	link_idx = dplane_ctx_gre_get_link_ifindex(ctx); + +	rta_info = nl_attr_nest(&req->n, buflen, IFLA_LINKINFO); +	if (!rta_info) +		return 0; +	if (!nl_attr_put(&req->n, buflen, IFLA_INFO_KIND, "gre", 3)) +		return 0; +	rta_data = nl_attr_nest(&req->n, buflen, IFLA_INFO_DATA); +	if (!rta_info) +		return 0; +	if (!nl_attr_put32(&req->n, buflen, IFLA_GRE_LINK, link_idx)) +		return 0; +	nl_attr_nest_end(&req->n, rta_data); +	nl_attr_nest_end(&req->n, rta_info); + +	return NLMSG_ALIGN(req->n.nlmsg_len); +} +  static int netlink_extract_bridge_info(struct rtattr *link_data,  				       struct zebra_l2info_bridge *bridge_info)  { @@ -524,9 +564,13 @@ static int netlink_extract_gre_info(struct rtattr *link_data,  	if (!attr[IFLA_GRE_LINK]) {  		if (IS_ZEBRA_DEBUG_KERNEL)  			zlog_debug("IFLA_GRE_LINK missing from GRE IF message"); -	} else +	} else {  		gre_info->ifindex_link =  			*(ifindex_t *)RTA_DATA(attr[IFLA_GRE_LINK]); +		if (IS_ZEBRA_DEBUG_KERNEL) +			zlog_debug("IFLA_GRE_LINK obtained is %u", +				   gre_info->ifindex_link); +	}  	if (attr[IFLA_GRE_IKEY])  		gre_info->ikey = *(uint32_t *)RTA_DATA(attr[IFLA_GRE_IKEY]);  	if (attr[IFLA_GRE_OKEY]) @@ -986,6 +1030,20 @@ static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family,  	return netlink_request(netlink_cmd, &req);  } +enum netlink_msg_status +netlink_put_gre_set_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx) +{ +	enum dplane_op_e op; +	enum netlink_msg_status ret; + +	op = dplane_ctx_get_op(ctx); +	assert(op == DPLANE_OP_GRE_SET); + +	ret = netlink_batch_add_msg(bth, ctx, netlink_gre_set_msg_encoder, false); + +	return ret; +} +  /* Interface lookup by netlink socket. */  int interface_lookup_netlink(struct zebra_ns *zns)  { diff --git a/zebra/if_netlink.h b/zebra/if_netlink.h index 0bbba81ca6..4f09b10b75 100644 --- a/zebra/if_netlink.h +++ b/zebra/if_netlink.h @@ -33,6 +33,9 @@ extern int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup);  extern int interface_lookup_netlink(struct zebra_ns *zns);  extern enum netlink_msg_status +netlink_put_gre_set_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx); + +extern enum netlink_msg_status  netlink_put_address_update_msg(struct nl_batch *bth,  			       struct zebra_dplane_ctx *ctx); diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index adb61023c1..cd22e95737 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -1360,6 +1360,9 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,  	case DPLANE_OP_IPSET_ENTRY_DELETE:  		return FRR_NETLINK_ERROR; +	case DPLANE_OP_GRE_SET: +		return netlink_put_gre_set_msg(bth, ctx); +  	case DPLANE_OP_NONE:  		return FRR_NETLINK_ERROR;  	} diff --git a/zebra/rt.h b/zebra/rt.h index daaa926a7d..f79ddbe958 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -81,9 +81,6 @@ extern int mpls_kernel_init(void);  extern uint32_t kernel_get_speed(struct interface *ifp, int *error);  extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute); -extern int kernel_configure_if_link(struct interface *ifp, -				    struct interface *link_ifp, ns_id_t ns_id); -  /*   * Southbound Initialization routines to get initial starting   * state. diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index d8405f277e..d2ec7da57c 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -3890,14 +3890,6 @@ netlink_put_neigh_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)  				     false);  } -int kernel_configure_if_link(struct interface *ifp, -			     struct interface *link_ifp, -			     ns_id_t ns_id) -{ -	/* TODO */ -	return 0; -} -  /*   * MPLS label forwarding table change via netlink interface, using dataplane   * context information. diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index ada828d016..006513ac9e 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -394,12 +394,6 @@ enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)  	return ZEBRA_DPLANE_REQUEST_SUCCESS;  } -int kernel_configure_if_link(struct interface *ifp, struct interface *link_ifp, -			     ns_id_t ns_id) -{ -	return 0; -} -  extern int kernel_interface_set_master(struct interface *master,  				       struct interface *slave)  { diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index d36c6becd7..22a6bf496b 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3435,22 +3435,40 @@ static inline void zebra_gre_source_set(ZAPI_HANDLER_ARGS)  	vrf_id_t link_vrf_id;  	struct interface *ifp;  	struct interface *ifp_link; -	ns_id_t ns_id;  	vrf_id_t vrf_id = zvrf->vrf->vrf_id; +	struct zebra_if *zif, *gre_zif; +	struct zebra_l2info_gre *gre_info;  	s = msg;  	STREAM_GETL(s, idx);  	ifp  = if_lookup_by_index(idx, vrf_id);  	STREAM_GETL(s, link_idx);  	STREAM_GETL(s, link_vrf_id); +  	ifp_link  = if_lookup_by_index(link_idx, link_vrf_id);  	if (!ifp_link || !ifp) {  		zlog_warn("GRE (index %u, VRF %u) or GRE link interface (index %u, VRF %u) not found, when setting GRE params",  			  idx, vrf_id, link_idx, link_vrf_id);  		return;  	} -	ns_id = zvrf->zns->ns_id; -	kernel_configure_if_link(ifp, ifp_link, ns_id); + +	if (!IS_ZEBRA_IF_GRE(ifp)) +		return; + +	gre_zif = (struct zebra_if *)ifp->info; +	zif = (struct zebra_if *)ifp_link->info; +	if (!zif || !gre_zif) +		return; + +	gre_info = &zif->l2info.gre; +	if (!gre_info) +		return; + +	/* if gre link already set */ +	if (gre_zif->link && gre_zif->link == ifp_link) +		return; + +	dplane_gre_set(ifp, ifp_link);   stream_failure:  	return; diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index c8ee8f9051..565ab821df 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -271,6 +271,9 @@ struct dplane_rule_info {  	struct dplane_ctx_rule old;  }; +struct dplane_gre_ctx { +	uint32_t link_ifindex; +};  /*   * The context block used to exchange info about route updates across   * the boundary between the zebra main context (and pthread) and the @@ -327,6 +330,7 @@ struct zebra_dplane_ctx {  			struct zebra_pbr_ipset_info info;  		} ipset_entry;  		struct dplane_neigh_table neightable; +		struct dplane_gre_ctx gre;  	} u;  	/* Namespace info, used especially for netlink kernel communication */ @@ -469,6 +473,9 @@ static struct zebra_dplane_globals {  	_Atomic uint32_t dg_neightable_in;  	_Atomic uint32_t dg_neightable_errors; +	_Atomic uint32_t dg_gre_set_in; +	_Atomic uint32_t dg_gre_set_errors; +  	/* Dataplane pthread */  	struct frr_pthread *dg_pthread; @@ -713,6 +720,9 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)  			}  			list_delete(&ctx->u.iptable.interface_name_list);  		} +		break; +	case DPLANE_OP_GRE_SET: +		break;  	}  } @@ -979,6 +989,10 @@ const char *dplane_op2str(enum dplane_op_e op)  	case DPLANE_OP_NEIGH_TABLE_UPDATE:  		ret = "NEIGH_TABLE_UPDATE";  		break; + +	case DPLANE_OP_GRE_SET: +		ret = "GRE_SET"; +		break;  	}  	return ret; @@ -1772,6 +1786,15 @@ uint32_t dplane_ctx_neigh_get_update_flags(const struct zebra_dplane_ctx *ctx)  	return ctx->u.neigh.update_flags;  } +/* Accessor for GRE set */ +uint32_t +dplane_ctx_gre_get_link_ifindex(const struct zebra_dplane_ctx *ctx) +{ +	DPLANE_CTX_VALID(ctx); + +	return ctx->u.gre.link_ifindex; +} +  /* Accessors for PBR rule information */  int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx)  { @@ -4126,6 +4149,67 @@ dplane_pbr_ipset_entry_delete(struct zebra_pbr_ipset_entry *ipset)  }  /* + * Common helper api for GRE set + */ +enum zebra_dplane_result +dplane_gre_set(struct interface *ifp, struct interface *ifp_link) +{ +	enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; +	struct zebra_dplane_ctx *ctx; +	enum dplane_op_e op = DPLANE_OP_GRE_SET; +	int ret; +	struct zebra_ns *zns; + +	ctx = dplane_ctx_alloc(); + +	if (!ifp) +		return result; + +	if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { +		zlog_debug("init dplane ctx %s: if %s link %s%s", +			   dplane_op2str(op), ifp->name, +			   ifp_link ? "set" : "unset", ifp_link ? +			   ifp_link->name : ""); +	} + +	ctx->zd_op = op; +	ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; +	zns = zebra_ns_lookup(ifp->vrf_id); +	if (!zns) +		return result; +	dplane_ctx_ns_init(ctx, zns, false); + +	dplane_ctx_set_ifname(ctx, ifp->name); +	ctx->zd_vrf_id = ifp->vrf_id; +	ctx->zd_ifindex = ifp->ifindex; +	if (ifp_link) +		ctx->u.gre.link_ifindex = ifp_link->ifindex; +	else +		ctx->u.gre.link_ifindex = 0; + +	ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; + +	/* Enqueue context for processing */ +	ret = dplane_update_enqueue(ctx); + +	/* Update counter */ +	atomic_fetch_add_explicit(&zdplane_info.dg_gre_set_in, 1, +				  memory_order_relaxed); + +	if (ret == AOK) +		result = ZEBRA_DPLANE_REQUEST_QUEUED; +	else { +		atomic_fetch_add_explicit( +			&zdplane_info.dg_gre_set_errors, 1, +			memory_order_relaxed); +		if (ctx) +			dplane_ctx_free(&ctx); +		result = ZEBRA_DPLANE_REQUEST_FAILURE; +	} +	return result; +} + +/*   * Handler for 'show dplane'   */  int dplane_show_helper(struct vty *vty, bool detailed) @@ -4234,6 +4318,13 @@ int dplane_show_helper(struct vty *vty, bool detailed)  				    memory_order_relaxed);  	vty_out(vty, "Neighbor Table updates:       %"PRIu64"\n", incoming);  	vty_out(vty, "Neighbor Table errors:        %"PRIu64"\n", errs); + +	incoming = atomic_load_explicit(&zdplane_info.dg_gre_set_in, +					memory_order_relaxed); +	errs = atomic_load_explicit(&zdplane_info.dg_gre_set_errors, +				    memory_order_relaxed); +	vty_out(vty, "GRE set updates:       %"PRIu64"\n", incoming); +	vty_out(vty, "GRE set errors:        %"PRIu64"\n", errs);  	return CMD_SUCCESS;  } @@ -4680,6 +4771,12 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)  			   dplane_ctx_get_ifname(ctx),  			   family2str(dplane_ctx_neightable_get_family(ctx)));  		break; +	case DPLANE_OP_GRE_SET: +		zlog_debug("Dplane gre set op %s, ifp %s, link %u", +			   dplane_op2str(dplane_ctx_get_op(ctx)), +			   dplane_ctx_get_ifname(ctx), +			   ctx->u.gre.link_ifindex); +		break;  	}  } @@ -4808,6 +4905,12 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)  				memory_order_relaxed);  		break; +	case DPLANE_OP_GRE_SET: +		if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) +			atomic_fetch_add_explicit( +				&zdplane_info.dg_gre_set_errors, 1, +				memory_order_relaxed); +		break;  	/* Ignore 'notifications' - no-op */  	case DPLANE_OP_SYS_ROUTE_ADD:  	case DPLANE_OP_SYS_ROUTE_DELETE: diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 8d51d93cd4..5df58e6e99 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -171,6 +171,7 @@ enum dplane_op_e {  	DPLANE_OP_NEIGH_IP_DELETE,  	DPLANE_OP_NEIGH_TABLE_UPDATE, +	DPLANE_OP_GRE_SET,  };  /* @@ -527,6 +528,10 @@ dplane_ctx_neightable_get_mcast_probes(const struct zebra_dplane_ctx *ctx);  uint32_t  dplane_ctx_neightable_get_ucast_probes(const struct zebra_dplane_ctx *ctx); +/* Accessor for GRE set */ +uint32_t +dplane_ctx_gre_get_link_ifindex(const struct zebra_dplane_ctx *ctx); +  /* Namespace info - esp. for netlink communication */  const struct zebra_dplane_info *dplane_ctx_get_ns(  	const struct zebra_dplane_ctx *ctx); @@ -695,6 +700,12 @@ enum zebra_dplane_result dplane_neigh_table_update(const struct interface *ifp,  						   const uint32_t ucast_probes,  						   const uint32_t mcast_probes); +/* + * Enqueue a GRE set + */ +enum zebra_dplane_result +dplane_gre_set(struct interface *ifp, struct interface *ifp_link); +  /* Forward ref of zebra_pbr_rule */  struct zebra_pbr_rule; diff --git a/zebra/zebra_errors.h b/zebra/zebra_errors.h index fc0382a6cd..200a977a69 100644 --- a/zebra/zebra_errors.h +++ b/zebra/zebra_errors.h @@ -134,6 +134,7 @@ enum zebra_log_refs {  	EC_ZEBRA_DUPLICATE_NHG_MESSAGE,  	EC_ZEBRA_VRF_MISCONFIGURED,  	EC_ZEBRA_ES_CREATE, +	EC_ZEBRA_GRE_SET_UPDATE,  };  void zebra_error_init(void); diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 47651318a4..6b40eae5b7 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -2965,6 +2965,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)  	case DPLANE_OP_IPSET_ENTRY_ADD:  	case DPLANE_OP_IPSET_ENTRY_DELETE:  	case DPLANE_OP_NEIGH_TABLE_UPDATE: +	case DPLANE_OP_GRE_SET:  		break;  	} diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index bdacd411bd..dbc5c77fd9 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -4062,6 +4062,7 @@ static int rib_process_dplane_results(struct thread *thread)  			case DPLANE_OP_NEIGH_DISCOVER:  			case DPLANE_OP_BR_PORT_UPDATE:  			case DPLANE_OP_NEIGH_TABLE_UPDATE: +			case DPLANE_OP_GRE_SET:  			case DPLANE_OP_NONE:  				/* Don't expect this: just return the struct? */  				dplane_ctx_fini(&ctx);  | 
