Commit e312b3a1 authored by Junfeng Guo's avatar Junfeng Guo Committed by Tony Nguyen
Browse files

ice: add API for parser profile initialization



Add API ice_parser_profile_init() to init a parser profile based on
a parser result and a mask buffer. The ice_parser_profile struct is used
by the low level FXP engine to create HW profile/field vectors.

Reviewed-by: default avatarMarcin Szycik <marcin.szycik@linux.intel.com>
Signed-off-by: default avatarQi Zhang <qi.z.zhang@intel.com>
Signed-off-by: default avatarJunfeng Guo <junfeng.guo@intel.com>
Signed-off-by: default avatarAhmed Zaki <ahmed.zaki@intel.com>
Tested-by: default avatarRafal Romanowski <rafal.romanowski@intel.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 80a48007
Loading
Loading
Loading
Loading
+128 −2
Original line number Diff line number Diff line
@@ -2302,3 +2302,129 @@ int ice_parser_ecpri_tunnel_set(struct ice_parser *psr,
	return ice_tunnel_port_set(psr, ICE_LBL_BST_TYPE_UDP_ECPRI,
				   udp_port, on);
}

/**
 * ice_nearest_proto_id - find nearest protocol ID
 * @rslt: pointer to a parser result instance
 * @offset: a min value for the protocol offset
 * @proto_id: the protocol ID (output)
 * @proto_off: the protocol offset (output)
 *
 * From the protocols in @rslt, find the nearest protocol that has offset
 * larger than @offset.
 *
 * Return: if true, the protocol's ID and offset
 */
static bool ice_nearest_proto_id(struct ice_parser_result *rslt, u16 offset,
				 u8 *proto_id, u16 *proto_off)
{
	u16 dist = U16_MAX;
	u8 proto = 0;
	int i;

	for (i = 0; i < rslt->po_num; i++) {
		if (offset < rslt->po[i].offset)
			continue;
		if (offset - rslt->po[i].offset < dist) {
			proto = rslt->po[i].proto_id;
			dist = offset - rslt->po[i].offset;
		}
	}

	if (dist % 2)
		return false;

	*proto_id = proto;
	*proto_off = dist;

	return true;
}

/* default flag mask to cover GTP_EH_PDU, GTP_EH_PDU_LINK and TUN2
 * In future, the flag masks should learn from DDP
 */
#define ICE_KEYBUILD_FLAG_MASK_DEFAULT_SW	0x4002
#define ICE_KEYBUILD_FLAG_MASK_DEFAULT_ACL	0x0000
#define ICE_KEYBUILD_FLAG_MASK_DEFAULT_FD	0x6080
#define ICE_KEYBUILD_FLAG_MASK_DEFAULT_RSS	0x6010

/**
 * ice_parser_profile_init - initialize a FXP profile based on parser result
 * @rslt: a instance of a parser result
 * @pkt_buf: packet data buffer
 * @msk_buf: packet mask buffer
 * @buf_len: packet length
 * @blk: FXP pipeline stage
 * @prof: input/output parameter to save the profile
 *
 * Return: 0 on success or errno on failure.
 */
int ice_parser_profile_init(struct ice_parser_result *rslt,
			    const u8 *pkt_buf, const u8 *msk_buf,
			    int buf_len, enum ice_block blk,
			    struct ice_parser_profile *prof)
{
	u8 proto_id = U8_MAX;
	u16 proto_off = 0;
	u16 off;

	memset(prof, 0, sizeof(*prof));
	set_bit(rslt->ptype, prof->ptypes);
	if (blk == ICE_BLK_SW) {
		prof->flags	= rslt->flags_sw;
		prof->flags_msk	= ICE_KEYBUILD_FLAG_MASK_DEFAULT_SW;
	} else if (blk == ICE_BLK_ACL) {
		prof->flags	= rslt->flags_acl;
		prof->flags_msk	= ICE_KEYBUILD_FLAG_MASK_DEFAULT_ACL;
	} else if (blk == ICE_BLK_FD) {
		prof->flags	= rslt->flags_fd;
		prof->flags_msk	= ICE_KEYBUILD_FLAG_MASK_DEFAULT_FD;
	} else if (blk == ICE_BLK_RSS) {
		prof->flags	= rslt->flags_rss;
		prof->flags_msk	= ICE_KEYBUILD_FLAG_MASK_DEFAULT_RSS;
	} else {
		return -EINVAL;
	}

	for (off = 0; off < buf_len - 1; off++) {
		if (msk_buf[off] == 0 && msk_buf[off + 1] == 0)
			continue;
		if (!ice_nearest_proto_id(rslt, off, &proto_id, &proto_off))
			continue;
		if (prof->fv_num >= ICE_PARSER_FV_MAX)
			return -EINVAL;

		prof->fv[prof->fv_num].proto_id	= proto_id;
		prof->fv[prof->fv_num].offset	= proto_off;
		prof->fv[prof->fv_num].spec	= *(const u16 *)&pkt_buf[off];
		prof->fv[prof->fv_num].msk	= *(const u16 *)&msk_buf[off];
		prof->fv_num++;
	}

	return 0;
}

/**
 * ice_parser_profile_dump - dump an FXP profile info
 * @hw: pointer to the hardware structure
 * @prof: profile info to dump
 */
void ice_parser_profile_dump(struct ice_hw *hw,
			     struct ice_parser_profile *prof)
{
	struct device *dev = ice_hw_to_dev(hw);
	u16 i;

	dev_info(dev, "ptypes:\n");
	for (i = 0; i < ICE_FLOW_PTYPE_MAX; i++)
		if (test_bit(i, prof->ptypes))
			dev_info(dev, "\t%u\n", i);

	for (i = 0; i < prof->fv_num; i++)
		dev_info(dev, "proto = %u, offset = %2u, spec = 0x%04x, mask = 0x%04x\n",
			 prof->fv[i].proto_id, prof->fv[i].offset,
			 prof->fv[i].spec, prof->fv[i].msk);

	dev_info(dev, "flags = 0x%04x\n", prof->flags);
	dev_info(dev, "flags_msk = 0x%04x\n", prof->flags_msk);
}
+26 −0
Original line number Diff line number Diff line
@@ -451,6 +451,8 @@ struct ice_parser_proto_off {

#define ICE_PARSER_PROTO_OFF_PAIR_SIZE	16
#define ICE_PARSER_FLAG_PSR_SIZE	8
#define ICE_PARSER_FV_SIZE		48
#define ICE_PARSER_FV_MAX		24
#define ICE_BT_TUN_PORT_OFF_H		16
#define ICE_BT_TUN_PORT_OFF_L		15
#define ICE_BT_VM_OFF			0
@@ -511,4 +513,28 @@ int ice_parser_ecpri_tunnel_set(struct ice_parser *psr, u16 udp_port, bool on);
int ice_parser_run(struct ice_parser *psr, const u8 *pkt_buf,
		   int pkt_len, struct ice_parser_result *rslt);
void ice_parser_result_dump(struct ice_hw *hw, struct ice_parser_result *rslt);

struct ice_parser_fv {
	u8 proto_id;	/* hardware protocol ID */
	u16 offset;	/* offset from the start of the protocol header */
	u16 spec;	/* pattern to match */
	u16 msk;	/* pattern mask */
};

struct ice_parser_profile {
	/* array of field vectors */
	struct ice_parser_fv fv[ICE_PARSER_FV_SIZE];
	int fv_num;		/* # of field vectors must <= 48 */
	u16 flags;		/* key builder flags */
	u16 flags_msk;		/* key builder flag mask */

	DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX); /* PTYPE bitmap */
};

int ice_parser_profile_init(struct ice_parser_result *rslt,
			    const u8 *pkt_buf, const u8 *msk_buf,
			    int buf_len, enum ice_block blk,
			    struct ice_parser_profile *prof);
void ice_parser_profile_dump(struct ice_hw *hw,
			     struct ice_parser_profile *prof);
#endif /* _ICE_PARSER_H_ */