diff options
| author | Jakub Urbańczyk <xthaid@gmail.com> | 2020-05-24 19:03:25 +0200 | 
|---|---|---|
| committer | Jakub Urbańczyk <xthaid@gmail.com> | 2020-06-10 16:18:45 +0200 | 
| commit | f62e5480ec901d3e9563b715a556c1d9f68822ee (patch) | |
| tree | 3afdaeb00e81a54a05a603ac6bf2bcd5383ecbdd /zebra/rule_netlink.c | |
| parent | 60d8d43be4f86cc551fde4c8f791bc96ee58147c (diff) | |
zebra: convert ip rule installation to use dplane thread
 * Implement new dataplane operations
 * Convert existing code to use dataplane context object
 * Modify function preparing netlink message to use dataplane
   context object
Signed-off-by: Jakub Urbańczyk <xthaid@gmail.com>
Diffstat (limited to 'zebra/rule_netlink.c')
| -rw-r--r-- | zebra/rule_netlink.c | 150 | 
1 files changed, 69 insertions, 81 deletions
diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c index a5a605f27e..66073042cd 100644 --- a/zebra/rule_netlink.c +++ b/zebra/rule_netlink.c @@ -41,6 +41,7 @@  #include "zebra/rule_netlink.h"  #include "zebra/zebra_pbr.h"  #include "zebra/zebra_errors.h" +#include "zebra/zebra_dplane.h"  /* definitions */ @@ -49,10 +50,13 @@  /* Private functions */  /* Install or uninstall specified rule for a specific interface. - * Form netlink message and ship it. Currently, notify status after - * waiting for netlink status. + * Form netlink message and ship it.   */ -static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule) +static int +netlink_rule_update_internal(int cmd, const struct zebra_dplane_ctx *ctx, +			     uint32_t filter_bm, uint32_t priority, +			     uint32_t table, const struct prefix *src_ip, +			     const struct prefix *dst_ip, uint32_t fwmark)  {  	uint8_t protocol = RTPROT_ZEBRA;  	int family; @@ -64,11 +68,12 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)  	} req;  	struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);  	struct sockaddr_nl snl; +	const char *ifname = dplane_ctx_get_ifname(ctx);  	char buf1[PREFIX_STRLEN];  	char buf2[PREFIX_STRLEN];  	memset(&req, 0, sizeof(req) - NL_PKT_BUF_SIZE); -	family = PREFIX_FAMILY(&rule->rule.filter.src_ip); +	family = PREFIX_FAMILY(src_ip);  	bytelen = (family == AF_INET ? 4 : 16);  	req.n.nlmsg_type = cmd; @@ -83,119 +88,100 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)  		  FRA_PROTOCOL, &protocol, sizeof(protocol));  	/* rule's pref # */ -	addattr32(&req.n, sizeof(req), FRA_PRIORITY, rule->rule.priority); +	addattr32(&req.n, sizeof(req), FRA_PRIORITY, priority);  	/* interface on which applied */ -	addattr_l(&req.n, sizeof(req), FRA_IFNAME, rule->ifname, -		  strlen(rule->ifname) + 1); +	addattr_l(&req.n, sizeof(req), FRA_IFNAME, ifname, strlen(ifname) + 1);  	/* source IP, if specified */ -	if (IS_RULE_FILTERING_ON_SRC_IP(rule)) { -		req.frh.src_len = rule->rule.filter.src_ip.prefixlen; -		addattr_l(&req.n, sizeof(req), FRA_SRC, -			  &rule->rule.filter.src_ip.u.prefix, bytelen); +	if (filter_bm & PBR_FILTER_SRC_IP) { +		req.frh.src_len = src_ip->prefixlen; +		addattr_l(&req.n, sizeof(req), FRA_SRC, &src_ip->u.prefix, +			  bytelen);  	}  	/* destination IP, if specified */ -	if (IS_RULE_FILTERING_ON_DST_IP(rule)) { -		req.frh.dst_len = rule->rule.filter.dst_ip.prefixlen; -		addattr_l(&req.n, sizeof(req), FRA_DST, -			  &rule->rule.filter.dst_ip.u.prefix, bytelen); +	if (filter_bm & PBR_FILTER_DST_IP) { +		req.frh.dst_len = dst_ip->prefixlen; +		addattr_l(&req.n, sizeof(req), FRA_DST, &dst_ip->u.prefix, +			  bytelen);  	}  	/* fwmark, if specified */ -	if (IS_RULE_FILTERING_ON_FWMARK(rule)) { -		addattr32(&req.n, sizeof(req), FRA_FWMARK, -			  rule->rule.filter.fwmark); -	} +	if (filter_bm & PBR_FILTER_FWMARK) +		addattr32(&req.n, sizeof(req), FRA_FWMARK, fwmark);  	/* Route table to use to forward, if filter criteria matches. */ -	if (rule->rule.action.table < 256) -		req.frh.table = rule->rule.action.table; +	if (table < 256) +		req.frh.table = table;  	else {  		req.frh.table = RT_TABLE_UNSPEC; -		addattr32(&req.n, sizeof(req), FRA_TABLE, -			  rule->rule.action.table); +		addattr32(&req.n, sizeof(req), FRA_TABLE, table);  	}  	if (IS_ZEBRA_DEBUG_KERNEL)  		zlog_debug(  			"Tx %s family %s IF %s(%u) Pref %u Fwmark %u Src %s Dst %s Table %u",  			nl_msg_type_to_str(cmd), nl_family_to_str(family), -			rule->ifname, rule->rule.ifindex, rule->rule.priority, -			rule->rule.filter.fwmark, -			prefix2str(&rule->rule.filter.src_ip, buf1, -				   sizeof(buf1)), -			prefix2str(&rule->rule.filter.dst_ip, buf2, -				   sizeof(buf2)), -			rule->rule.action.table); +			ifname, dplane_ctx_get_ifindex(ctx), priority, fwmark, +			prefix2str(src_ip, buf1, sizeof(buf1)), +			prefix2str(dst_ip, buf2, sizeof(buf2)), table); -	/* Ship off the message. -	 * Note: Currently, netlink_talk() is a blocking call which returns -	 * back the status. -	 */  	memset(&snl, 0, sizeof(snl));  	snl.nl_family = AF_NETLINK;  	return netlink_talk(netlink_talk_filter, &req.n,  			    &zns->netlink_cmd, zns, 0);  } -  /* Public functions */ -/* - * Install specified rule for a specific interface. The preference is what - * goes in the rule to denote relative ordering; it may or may not be the - * same as the rule's user-defined sequence number. - */ -enum zebra_dplane_result kernel_add_pbr_rule(struct zebra_pbr_rule *rule) -{ -	int ret = 0; - -	ret = netlink_rule_update(RTM_NEWRULE, rule); -	kernel_pbr_rule_add_del_status(rule, -				       (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS -					      : ZEBRA_DPLANE_INSTALL_FAILURE); - -	return ZEBRA_DPLANE_REQUEST_SUCCESS; -}  /* - * Uninstall specified rule for a specific interface. + * Add, update or delete a rule from the + * kernel, using info from a dataplane context.   */ -enum zebra_dplane_result kernel_del_pbr_rule(struct zebra_pbr_rule *rule) +enum zebra_dplane_result kernel_pbr_rule_update(struct zebra_dplane_ctx *ctx)  { -	int ret = 0; - -	ret = netlink_rule_update(RTM_DELRULE, rule); -	kernel_pbr_rule_add_del_status(rule, -				       (!ret) ? ZEBRA_DPLANE_DELETE_SUCCESS -					      : ZEBRA_DPLANE_DELETE_FAILURE); - -	return ZEBRA_DPLANE_REQUEST_SUCCESS; -} +	enum dplane_op_e op; +	int cmd; +	int ret; -/* - * Update specified rule for a specific interface. - */ -enum zebra_dplane_result kernel_update_pbr_rule(struct zebra_pbr_rule *old_rule, -						struct zebra_pbr_rule *new_rule) -{ -	int ret = 0; +	op = dplane_ctx_get_op(ctx); +	if (op == DPLANE_OP_RULE_ADD || op == DPLANE_OP_RULE_UPDATE) +		cmd = RTM_NEWRULE; +	else if (op == DPLANE_OP_RULE_DELETE) +		cmd = RTM_DELRULE; +	else { +		flog_err( +			EC_ZEBRA_PBR_RULE_UPDATE, +			"Context received for kernel rule update with incorrect OP code (%u)", +			op); +		return ZEBRA_DPLANE_REQUEST_FAILURE; +	} -	/* Add the new, updated one */ -	ret = netlink_rule_update(RTM_NEWRULE, new_rule); +	ret = netlink_rule_update_internal( +		cmd, ctx, dplane_ctx_rule_get_filter_bm(ctx), +		dplane_ctx_rule_get_priority(ctx), +		dplane_ctx_rule_get_table(ctx), dplane_ctx_rule_get_src_ip(ctx), +		dplane_ctx_rule_get_dst_ip(ctx), +		dplane_ctx_rule_get_fwmark(ctx));  	/**  	 * Delete the old one.  	 *  	 * Don't care about this result right?  	 */ -	netlink_rule_update(RTM_DELRULE, old_rule); - -	kernel_pbr_rule_add_del_status(new_rule, -				       (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS -					      : ZEBRA_DPLANE_INSTALL_FAILURE); - -	return ZEBRA_DPLANE_REQUEST_SUCCESS; +	if (op == DPLANE_OP_RULE_UPDATE) +		netlink_rule_update_internal( +			RTM_DELRULE, ctx, +			dplane_ctx_rule_get_old_filter_bm(ctx), +			dplane_ctx_rule_get_old_priority(ctx), +			dplane_ctx_rule_get_old_table(ctx), +			dplane_ctx_rule_get_old_src_ip(ctx), +			dplane_ctx_rule_get_old_dst_ip(ctx), +			dplane_ctx_rule_get_old_fwmark(ctx)); + + +	return (ret == 0 ? ZEBRA_DPLANE_REQUEST_SUCCESS +			 : ZEBRA_DPLANE_REQUEST_FAILURE);  }  /* @@ -296,14 +282,16 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)  		 * It should have been flushed on a previous shutdown.  		 */  		if (startup && proto == RTPROT_ZEBRA) { -			int ret; +			enum zebra_dplane_result ret; -			ret = netlink_rule_update(RTM_DELRULE, &rule); +			ret = dplane_pbr_rule_delete(&rule);  			zlog_debug(  				"%s: %s leftover rule: family %s IF %s(%u) Pref %u Src %s Dst %s Table %u",  				__func__, -				((ret == 0) ? "Removed" : "Failed to remove"), +				((ret == ZEBRA_DPLANE_REQUEST_FAILURE) +					 ? "Failed to remove" +					 : "Removed"),  				nl_family_to_str(frh->family), rule.ifname,  				rule.rule.ifindex, rule.rule.priority,  				prefix2str(&rule.rule.filter.src_ip, buf1,  | 
