src/dpdk/drivers/net/txgbe/txgbe_flow.c
static int
cons_parse_syn_filter(const struct rte_flow_attr *attr,
				const struct rte_flow_item pattern[],
				const struct rte_flow_action actions[],
				struct rte_eth_syn_filter *filter,
				struct rte_flow_error *error)
{
	const struct rte_flow_item *item;
	const struct rte_flow_action *act;
	const struct rte_flow_item_tcp *tcp_spec;
	const struct rte_flow_item_tcp *tcp_mask;
	const struct rte_flow_action_queue *act_q;

	if (!pattern) {
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM_NUM,
				NULL, "NULL pattern.");
		return -rte_errno;
	}

	if (!actions) {
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ACTION_NUM,
				NULL, "NULL action.");
		return -rte_errno;
	}

	if (!attr) {
		rte_flow_error_set(error, EINVAL,
				   RTE_FLOW_ERROR_TYPE_ATTR,
				   NULL, "NULL attribute.");
		return -rte_errno;
	}


	/* the first not void item should be MAC or IPv4 or IPv6 or TCP */
	item = next_no_void_pattern(pattern, NULL);
	if (item->type != RTE_FLOW_ITEM_TYPE_ETH &&
	    item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
	    item->type != RTE_FLOW_ITEM_TYPE_IPV6 &&
	    item->type != RTE_FLOW_ITEM_TYPE_TCP) {
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Not supported by syn filter");
		return -rte_errno;
	}
		/*Not supported last point for range*/
	if (item->last) {
		rte_flow_error_set(error, EINVAL,
			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
			item, "Not supported last point for range");
		return -rte_errno;
	}

	/* Skip Ethernet */
	if (item->type == RTE_FLOW_ITEM_TYPE_ETH) {
		/* if the item is MAC, the content should be NULL */
		if (item->spec || item->mask) {
			rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Invalid SYN address mask");
			return -rte_errno;
		}

		/* check if the next not void item is IPv4 or IPv6 */
		item = next_no_void_pattern(pattern, item);
		if (item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
		    item->type != RTE_FLOW_ITEM_TYPE_IPV6) {
			rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Not supported by syn filter");
			return -rte_errno;
		}
	}

	/* Skip IP */
	if (item->type == RTE_FLOW_ITEM_TYPE_IPV4 ||
	    item->type == RTE_FLOW_ITEM_TYPE_IPV6) {
		/* if the item is IP, the content should be NULL */
		if (item->spec || item->mask) {
			rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Invalid SYN mask");
			return -rte_errno;
		}

		/* check if the next not void item is TCP */
		item = next_no_void_pattern(pattern, item);
		if (item->type != RTE_FLOW_ITEM_TYPE_TCP) {
			rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Not supported by syn filter");
			return -rte_errno;
		}
	}

	/* Get the TCP info. Only support SYN. */
	if (!item->spec || !item->mask) {
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Invalid SYN mask");
		return -rte_errno;
	}
	/*Not supported last point for range*/
	if (item->last) {
		rte_flow_error_set(error, EINVAL,
			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
			item, "Not supported last point for range");
		return -rte_errno;
	}

	tcp_spec = item->spec;
	tcp_mask = item->mask;
	if (!(tcp_spec->hdr.tcp_flags & RTE_TCP_SYN_FLAG) ||
	    tcp_mask->hdr.src_port ||
	    tcp_mask->hdr.dst_port ||
	    tcp_mask->hdr.sent_seq ||
	    tcp_mask->hdr.recv_ack ||
	    tcp_mask->hdr.data_off ||
	    tcp_mask->hdr.tcp_flags != RTE_TCP_SYN_FLAG ||
	    tcp_mask->hdr.rx_win ||
	    tcp_mask->hdr.cksum ||
	    tcp_mask->hdr.tcp_urp) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Not supported by syn filter");
		return -rte_errno;
	}

	/* check if the next not void item is END */
	item = next_no_void_pattern(pattern, item);
	if (item->type != RTE_FLOW_ITEM_TYPE_END) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Not supported by syn filter");
		return -rte_errno;
	}

	/* check if the first not void action is QUEUE. */
	act = next_no_void_action(actions, NULL);
	if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ACTION,
				act, "Not supported action.");
		return -rte_errno;
	}

	act_q = (const struct rte_flow_action_queue *)act->conf;
	filter->queue = act_q->index;
	if (filter->queue >= TXGBE_MAX_RX_QUEUE_NUM) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ACTION,
				act, "Not supported action.");
		return -rte_errno;
	}

	/* check if the next not void item is END */
	act = next_no_void_action(actions, act);
	if (act->type != RTE_FLOW_ACTION_TYPE_END) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ACTION,
				act, "Not supported action.");
		return -rte_errno;
	}

	/* parse attr */
	/* must be input direction */
	if (!attr->ingress) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
			RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
			attr, "Only support ingress.");
		return -rte_errno;
	}

	/* not supported */
	if (attr->egress) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
			RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
			attr, "Not support egress.");
		return -rte_errno;
	}

	/* not supported */
	if (attr->transfer) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
			RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
			attr, "No support for transfer.");
		return -rte_errno;
	}

	/* Support 2 priorities, the lowest or highest. */
	if (!attr->priority) {
		filter->hig_pri = 0;
	} else if (attr->priority == (uint32_t)~0U) {
		filter->hig_pri = 1;
	} else {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
			RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
			attr, "Not support priority.");
		return -rte_errno;
	}

	return 0;
}
/**
 * Parse the rule to see if it is a TCP SYN rule.
 * And get the TCP SYN filter info BTW.
 * pattern:
 * The first not void item must be ETH.
 * The second not void item must be IPV4 or IPV6.
 * The third not void item must be TCP.
 * The next not void item must be END.
 * action:
 * The first not void action should be QUEUE.
 * The next not void action should be END.
 * pattern example:
 * ITEM		Spec			Mask
 * ETH		NULL			NULL
 * IPV4/IPV6	NULL			NULL
 * TCP		tcp_flags	0x02	0xFF
 * END
 * other members in mask and spec should set to 0x00.
 * item->last should be NULL.
 */
Parse the rule to see if it is a TCP SYN rule.
And get the TCP SYN filter info BTW.
pattern:
The first not void item must be ETH.
The second not void item must be IPV4 or IPV6.
The third not void item must be TCP.
The next not void item must be END.
action:
The first not void action should be QUEUE.
The next not void action should be END.
Parse the rule to see if it is a TCP SYN rule . And get the TCP SYN filter info BTW . pattern : The first not void item must be ETH . The second not void item must be IPV4 or IPV6 . The third not void item must be TCP . The next not void item must be END . action : The first not void action should be QUEUE . The next not void action should be END .
static int
cons_parse_syn_filter(const struct rte_flow_attr *attr,
				const struct rte_flow_item pattern[],
				const struct rte_flow_action actions[],
				struct rte_eth_syn_filter *filter,
				struct rte_flow_error *error)
{
	const struct rte_flow_item *item;
	const struct rte_flow_action *act;
	const struct rte_flow_item_tcp *tcp_spec;
	const struct rte_flow_item_tcp *tcp_mask;
	const struct rte_flow_action_queue *act_q;
	if (!pattern) {
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM_NUM,
				NULL, "NULL pattern.");
		return -rte_errno;
	}
	if (!actions) {
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ACTION_NUM,
				NULL, "NULL action.");
		return -rte_errno;
	}
	if (!attr) {
		rte_flow_error_set(error, EINVAL,
				   RTE_FLOW_ERROR_TYPE_ATTR,
				   NULL, "NULL attribute.");
		return -rte_errno;
	}
	item = next_no_void_pattern(pattern, NULL);
	if (item->type != RTE_FLOW_ITEM_TYPE_ETH &&
	    item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
	    item->type != RTE_FLOW_ITEM_TYPE_IPV6 &&
	    item->type != RTE_FLOW_ITEM_TYPE_TCP) {
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Not supported by syn filter");
		return -rte_errno;
	}
	if (item->last) {
		rte_flow_error_set(error, EINVAL,
			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
			item, "Not supported last point for range");
		return -rte_errno;
	}
	if (item->type == RTE_FLOW_ITEM_TYPE_ETH) {
		if (item->spec || item->mask) {
			rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Invalid SYN address mask");
			return -rte_errno;
		}
		item = next_no_void_pattern(pattern, item);
		if (item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
		    item->type != RTE_FLOW_ITEM_TYPE_IPV6) {
			rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Not supported by syn filter");
			return -rte_errno;
		}
	}
	if (item->type == RTE_FLOW_ITEM_TYPE_IPV4 ||
	    item->type == RTE_FLOW_ITEM_TYPE_IPV6) {
		if (item->spec || item->mask) {
			rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Invalid SYN mask");
			return -rte_errno;
		}
		item = next_no_void_pattern(pattern, item);
		if (item->type != RTE_FLOW_ITEM_TYPE_TCP) {
			rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Not supported by syn filter");
			return -rte_errno;
		}
	}
	if (!item->spec || !item->mask) {
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Invalid SYN mask");
		return -rte_errno;
	}
	if (item->last) {
		rte_flow_error_set(error, EINVAL,
			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
			item, "Not supported last point for range");
		return -rte_errno;
	}
	tcp_spec = item->spec;
	tcp_mask = item->mask;
	if (!(tcp_spec->hdr.tcp_flags & RTE_TCP_SYN_FLAG) ||
	    tcp_mask->hdr.src_port ||
	    tcp_mask->hdr.dst_port ||
	    tcp_mask->hdr.sent_seq ||
	    tcp_mask->hdr.recv_ack ||
	    tcp_mask->hdr.data_off ||
	    tcp_mask->hdr.tcp_flags != RTE_TCP_SYN_FLAG ||
	    tcp_mask->hdr.rx_win ||
	    tcp_mask->hdr.cksum ||
	    tcp_mask->hdr.tcp_urp) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Not supported by syn filter");
		return -rte_errno;
	}
	item = next_no_void_pattern(pattern, item);
	if (item->type != RTE_FLOW_ITEM_TYPE_END) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ITEM,
				item, "Not supported by syn filter");
		return -rte_errno;
	}
	act = next_no_void_action(actions, NULL);
	if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ACTION,
				act, "Not supported action.");
		return -rte_errno;
	}
	act_q = (const struct rte_flow_action_queue *)act->conf;
	filter->queue = act_q->index;
	if (filter->queue >= TXGBE_MAX_RX_QUEUE_NUM) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ACTION,
				act, "Not supported action.");
		return -rte_errno;
	}
	act = next_no_void_action(actions, act);
	if (act->type != RTE_FLOW_ACTION_TYPE_END) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
				RTE_FLOW_ERROR_TYPE_ACTION,
				act, "Not supported action.");
		return -rte_errno;
	}
	if (!attr->ingress) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
			RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
			attr, "Only support ingress.");
		return -rte_errno;
	}
	if (attr->egress) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
			RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
			attr, "Not support egress.");
		return -rte_errno;
	}
	if (attr->transfer) {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
			RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
			attr, "No support for transfer.");
		return -rte_errno;
	}
	if (!attr->priority) {
		filter->hig_pri = 0;
	} else if (attr->priority == (uint32_t)~0U) {
		filter->hig_pri = 1;
	} else {
		memset(filter, 0, sizeof(struct rte_eth_syn_filter));
		rte_flow_error_set(error, EINVAL,
			RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
			attr, "Not support priority.");
		return -rte_errno;
	}
	return 0;
}
static int cons_parse_syn_filter ( const struct rte_flow_attr * attr , const struct rte_flow_item pattern [ ] , const struct rte_flow_action actions [ ] , struct rte_eth_syn_filter * filter , struct rte_flow_error * error ) { const struct rte_flow_item * item ; const struct rte_flow_action * act ; const struct rte_flow_item_tcp * tcp_spec ; const struct rte_flow_item_tcp * tcp_mask ; const struct rte_flow_action_queue * act_q ; if ( ! pattern ) { rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ITEM_NUM , NULL , " " ) ; return - rte_errno ; } if ( ! actions ) { rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ACTION_NUM , NULL , " " ) ; return - rte_errno ; } if ( ! attr ) { rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ATTR , NULL , " " ) ; return - rte_errno ; } item = next_no_void_pattern ( pattern , NULL ) ; if ( item -> type != RTE_FLOW_ITEM_TYPE_ETH && item -> type != RTE_FLOW_ITEM_TYPE_IPV4 && item -> type != RTE_FLOW_ITEM_TYPE_IPV6 && item -> type != RTE_FLOW_ITEM_TYPE_TCP ) { rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ITEM , item , " " ) ; return - rte_errno ; } if ( item -> last ) { rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_UNSPECIFIED , item , " " ) ; return - rte_errno ; } if ( item -> type == RTE_FLOW_ITEM_TYPE_ETH ) { if ( item -> spec || item -> mask ) { rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ITEM , item , " " ) ; return - rte_errno ; } item = next_no_void_pattern ( pattern , item ) ; if ( item -> type != RTE_FLOW_ITEM_TYPE_IPV4 && item -> type != RTE_FLOW_ITEM_TYPE_IPV6 ) { rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ITEM , item , " " ) ; return - rte_errno ; } } if ( item -> type == RTE_FLOW_ITEM_TYPE_IPV4 || item -> type == RTE_FLOW_ITEM_TYPE_IPV6 ) { if ( item -> spec || item -> mask ) { rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ITEM , item , " " ) ; return - rte_errno ; } item = next_no_void_pattern ( pattern , item ) ; if ( item -> type != RTE_FLOW_ITEM_TYPE_TCP ) { rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ITEM , item , " " ) ; return - rte_errno ; } } if ( ! item -> spec || ! item -> mask ) { rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ITEM , item , " " ) ; return - rte_errno ; } if ( item -> last ) { rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_UNSPECIFIED , item , " " ) ; return - rte_errno ; } tcp_spec = item -> spec ; tcp_mask = item -> mask ; if ( ! ( tcp_spec -> hdr . tcp_flags & RTE_TCP_SYN_FLAG ) || tcp_mask -> hdr . src_port || tcp_mask -> hdr . dst_port || tcp_mask -> hdr . sent_seq || tcp_mask -> hdr . recv_ack || tcp_mask -> hdr . data_off || tcp_mask -> hdr . tcp_flags != RTE_TCP_SYN_FLAG || tcp_mask -> hdr . rx_win || tcp_mask -> hdr . cksum || tcp_mask -> hdr . tcp_urp ) { memset ( filter , 0 , sizeof ( struct rte_eth_syn_filter ) ) ; rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ITEM , item , " " ) ; return - rte_errno ; } item = next_no_void_pattern ( pattern , item ) ; if ( item -> type != RTE_FLOW_ITEM_TYPE_END ) { memset ( filter , 0 , sizeof ( struct rte_eth_syn_filter ) ) ; rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ITEM , item , " " ) ; return - rte_errno ; } act = next_no_void_action ( actions , NULL ) ; if ( act -> type != RTE_FLOW_ACTION_TYPE_QUEUE ) { memset ( filter , 0 , sizeof ( struct rte_eth_syn_filter ) ) ; rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ACTION , act , " " ) ; return - rte_errno ; } act_q = ( const struct rte_flow_action_queue * ) act -> conf ; filter -> queue = act_q -> index ; if ( filter -> queue >= TXGBE_MAX_RX_QUEUE_NUM ) { memset ( filter , 0 , sizeof ( struct rte_eth_syn_filter ) ) ; rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ACTION , act , " " ) ; return - rte_errno ; } act = next_no_void_action ( actions , act ) ; if ( act -> type != RTE_FLOW_ACTION_TYPE_END ) { memset ( filter , 0 , sizeof ( struct rte_eth_syn_filter ) ) ; rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ACTION , act , " " ) ; return - rte_errno ; } if ( ! attr -> ingress ) { memset ( filter , 0 , sizeof ( struct rte_eth_syn_filter ) ) ; rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ATTR_INGRESS , attr , " " ) ; return - rte_errno ; } if ( attr -> egress ) { memset ( filter , 0 , sizeof ( struct rte_eth_syn_filter ) ) ; rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ATTR_EGRESS , attr , " " ) ; return - rte_errno ; } if ( attr -> transfer ) { memset ( filter , 0 , sizeof ( struct rte_eth_syn_filter ) ) ; rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER , attr , " " ) ; return - rte_errno ; } if ( ! attr -> priority ) { filter -> hig_pri = 0 ; } else if ( attr -> priority == ( uint32_t ) ~ 0U ) { filter -> hig_pri = 1 ; } else { memset ( filter , 0 , sizeof ( struct rte_eth_syn_filter ) ) ; rte_flow_error_set ( error , EINVAL , RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY , attr , " " ) ; return - rte_errno ; } return 0 ; }
Parse the rule to see if it is a TCP SYN rule.
Parse the rule to see if it is a TCP SYN rule .
/* the first not void item should be MAC or IPv4 or IPv6 or TCP */ /*Not supported last point for range*/ /* Skip Ethernet */ /* if the item is MAC, the content should be NULL */ /* check if the next not void item is IPv4 or IPv6 */ /* Skip IP */ /* if the item is IP, the content should be NULL */ /* check if the next not void item is TCP */ /* Get the TCP info. Only support SYN. */ /*Not supported last point for range*/ /* check if the next not void item is END */ /* check if the first not void action is QUEUE. */ /* check if the next not void item is END */ /* parse attr */ /* must be input direction */ /* not supported */ /* not supported */ /* Support 2 priorities, the lowest or highest. */