target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/tc.c
static int rtl83xx_parse_flow_rule(struct rtl838x_switch_priv *priv,
			      struct flow_rule *rule, struct rtl83xx_flow *flow)
{
	struct flow_dissector *dissector = rule->match.dissector;

	pr_debug("In %s\n", __func__);
	/* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */
	if ((dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) == 0 ||
	    (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC)) == 0) {
		pr_err("Cannot form TC key: used_keys = 0x%x\n", dissector->used_keys);
		return -EOPNOTSUPP;
	}

	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
		struct flow_match_basic match;

		pr_debug("%s: BASIC\n", __func__);
		flow_rule_match_basic(rule, &match);
		if (match.key->n_proto == htons(ETH_P_ARP))
			flow->rule.frame_type = 0;
		if (match.key->n_proto == htons(ETH_P_IP))
			flow->rule.frame_type = 2;
		if (match.key->n_proto == htons(ETH_P_IPV6))
			flow->rule.frame_type = 3;
		if ((match.key->n_proto == htons(ETH_P_ARP)) || flow->rule.frame_type)
			flow->rule.frame_type_m = 3;
		if (flow->rule.frame_type >= 2) {
			if (match.key->ip_proto == IPPROTO_UDP)
				flow->rule.frame_type_l4 = 0;
			if (match.key->ip_proto == IPPROTO_TCP)
				flow->rule.frame_type_l4 = 1;
			if (match.key->ip_proto == IPPROTO_ICMP
				|| match.key->ip_proto ==IPPROTO_ICMPV6)
				flow->rule.frame_type_l4 = 2;
			if (match.key->ip_proto == IPPROTO_TCP)
				flow->rule.frame_type_l4 = 3;
			if ((match.key->ip_proto == IPPROTO_UDP) || flow->rule.frame_type_l4)
				flow->rule.frame_type_l4_m = 7;
		}
	}

	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
		struct flow_match_eth_addrs match;

		pr_debug("%s: ETH_ADDR\n", __func__);
		flow_rule_match_eth_addrs(rule, &match);
		ether_addr_copy(flow->rule.dmac, match.key->dst);
		ether_addr_copy(flow->rule.dmac_m, match.mask->dst);
		ether_addr_copy(flow->rule.smac, match.key->src);
		ether_addr_copy(flow->rule.smac_m, match.mask->src);
	}

	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
		struct flow_match_vlan match;

		pr_debug("%s: VLAN\n", __func__);
		flow_rule_match_vlan(rule, &match);
		flow->rule.itag = match.key->vlan_id;
		flow->rule.itag_m = match.mask->vlan_id;
		// TODO: What about match.key->vlan_priority ?
	}

	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
		struct flow_match_ipv4_addrs match;

		pr_debug("%s: IPV4\n", __func__);
		flow_rule_match_ipv4_addrs(rule, &match);
		flow->rule.is_ipv6 = false;
		flow->rule.dip = match.key->dst;
		flow->rule.dip_m = match.mask->dst;
		flow->rule.sip = match.key->src;
		flow->rule.sip_m = match.mask->src;
	} else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
		struct flow_match_ipv6_addrs match;

		pr_debug("%s: IPV6\n", __func__);
		flow->rule.is_ipv6 = true;
		flow_rule_match_ipv6_addrs(rule, &match);
		flow->rule.dip6 = match.key->dst;
		flow->rule.dip6_m = match.mask->dst;
		flow->rule.sip6 = match.key->src;
		flow->rule.sip6_m = match.mask->src;
	}

	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
		struct flow_match_ports match;

		pr_debug("%s: PORTS\n", __func__);
		flow_rule_match_ports(rule, &match);
		flow->rule.dport = match.key->dst;
		flow->rule.dport_m = match.mask->dst;
		flow->rule.sport = match.key->src;
		flow->rule.sport_m = match.mask->src;
	}

	// TODO: ICMP
	return 0;
}
/*
 * Parse the flow rule for the matching conditions
 */
Parse the flow rule for the matching conditions
Parse the flow rule for the matching conditions
static int rtl83xx_parse_flow_rule(struct rtl838x_switch_priv *priv,
			      struct flow_rule *rule, struct rtl83xx_flow *flow)
{
	struct flow_dissector *dissector = rule->match.dissector;
	pr_debug("In %s\n", __func__);
	if ((dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) == 0 ||
	    (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC)) == 0) {
		pr_err("Cannot form TC key: used_keys = 0x%x\n", dissector->used_keys);
		return -EOPNOTSUPP;
	}
	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
		struct flow_match_basic match;
		pr_debug("%s: BASIC\n", __func__);
		flow_rule_match_basic(rule, &match);
		if (match.key->n_proto == htons(ETH_P_ARP))
			flow->rule.frame_type = 0;
		if (match.key->n_proto == htons(ETH_P_IP))
			flow->rule.frame_type = 2;
		if (match.key->n_proto == htons(ETH_P_IPV6))
			flow->rule.frame_type = 3;
		if ((match.key->n_proto == htons(ETH_P_ARP)) || flow->rule.frame_type)
			flow->rule.frame_type_m = 3;
		if (flow->rule.frame_type >= 2) {
			if (match.key->ip_proto == IPPROTO_UDP)
				flow->rule.frame_type_l4 = 0;
			if (match.key->ip_proto == IPPROTO_TCP)
				flow->rule.frame_type_l4 = 1;
			if (match.key->ip_proto == IPPROTO_ICMP
				|| match.key->ip_proto ==IPPROTO_ICMPV6)
				flow->rule.frame_type_l4 = 2;
			if (match.key->ip_proto == IPPROTO_TCP)
				flow->rule.frame_type_l4 = 3;
			if ((match.key->ip_proto == IPPROTO_UDP) || flow->rule.frame_type_l4)
				flow->rule.frame_type_l4_m = 7;
		}
	}
	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
		struct flow_match_eth_addrs match;
		pr_debug("%s: ETH_ADDR\n", __func__);
		flow_rule_match_eth_addrs(rule, &match);
		ether_addr_copy(flow->rule.dmac, match.key->dst);
		ether_addr_copy(flow->rule.dmac_m, match.mask->dst);
		ether_addr_copy(flow->rule.smac, match.key->src);
		ether_addr_copy(flow->rule.smac_m, match.mask->src);
	}
	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
		struct flow_match_vlan match;
		pr_debug("%s: VLAN\n", __func__);
		flow_rule_match_vlan(rule, &match);
		flow->rule.itag = match.key->vlan_id;
		flow->rule.itag_m = match.mask->vlan_id;
	}
	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
		struct flow_match_ipv4_addrs match;
		pr_debug("%s: IPV4\n", __func__);
		flow_rule_match_ipv4_addrs(rule, &match);
		flow->rule.is_ipv6 = false;
		flow->rule.dip = match.key->dst;
		flow->rule.dip_m = match.mask->dst;
		flow->rule.sip = match.key->src;
		flow->rule.sip_m = match.mask->src;
	} else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
		struct flow_match_ipv6_addrs match;
		pr_debug("%s: IPV6\n", __func__);
		flow->rule.is_ipv6 = true;
		flow_rule_match_ipv6_addrs(rule, &match);
		flow->rule.dip6 = match.key->dst;
		flow->rule.dip6_m = match.mask->dst;
		flow->rule.sip6 = match.key->src;
		flow->rule.sip6_m = match.mask->src;
	}
	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
		struct flow_match_ports match;
		pr_debug("%s: PORTS\n", __func__);
		flow_rule_match_ports(rule, &match);
		flow->rule.dport = match.key->dst;
		flow->rule.dport_m = match.mask->dst;
		flow->rule.sport = match.key->src;
		flow->rule.sport_m = match.mask->src;
	}
	return 0;
}
static int rtl83xx_parse_flow_rule ( struct rtl838x_switch_priv * priv , struct flow_rule * rule , struct rtl83xx_flow * flow ) { struct flow_dissector * dissector = rule -> match . dissector ; pr_debug ( " \n " , __func__ ) ; if ( ( dissector -> used_keys & BIT ( FLOW_DISSECTOR_KEY_CONTROL ) ) == 0 || ( dissector -> used_keys & BIT ( FLOW_DISSECTOR_KEY_BASIC ) ) == 0 ) { pr_err ( " \n " , dissector -> used_keys ) ; return - EOPNOTSUPP ; } if ( flow_rule_match_key ( rule , FLOW_DISSECTOR_KEY_BASIC ) ) { struct flow_match_basic match ; pr_debug ( " \n " , __func__ ) ; flow_rule_match_basic ( rule , & match ) ; if ( match . key -> n_proto == htons ( ETH_P_ARP ) ) flow -> rule . frame_type = 0 ; if ( match . key -> n_proto == htons ( ETH_P_IP ) ) flow -> rule . frame_type = 2 ; if ( match . key -> n_proto == htons ( ETH_P_IPV6 ) ) flow -> rule . frame_type = 3 ; if ( ( match . key -> n_proto == htons ( ETH_P_ARP ) ) || flow -> rule . frame_type ) flow -> rule . frame_type_m = 3 ; if ( flow -> rule . frame_type >= 2 ) { if ( match . key -> ip_proto == IPPROTO_UDP ) flow -> rule . frame_type_l4 = 0 ; if ( match . key -> ip_proto == IPPROTO_TCP ) flow -> rule . frame_type_l4 = 1 ; if ( match . key -> ip_proto == IPPROTO_ICMP || match . key -> ip_proto == IPPROTO_ICMPV6 ) flow -> rule . frame_type_l4 = 2 ; if ( match . key -> ip_proto == IPPROTO_TCP ) flow -> rule . frame_type_l4 = 3 ; if ( ( match . key -> ip_proto == IPPROTO_UDP ) || flow -> rule . frame_type_l4 ) flow -> rule . frame_type_l4_m = 7 ; } } if ( flow_rule_match_key ( rule , FLOW_DISSECTOR_KEY_ETH_ADDRS ) ) { struct flow_match_eth_addrs match ; pr_debug ( " \n " , __func__ ) ; flow_rule_match_eth_addrs ( rule , & match ) ; ether_addr_copy ( flow -> rule . dmac , match . key -> dst ) ; ether_addr_copy ( flow -> rule . dmac_m , match . mask -> dst ) ; ether_addr_copy ( flow -> rule . smac , match . key -> src ) ; ether_addr_copy ( flow -> rule . smac_m , match . mask -> src ) ; } if ( flow_rule_match_key ( rule , FLOW_DISSECTOR_KEY_VLAN ) ) { struct flow_match_vlan match ; pr_debug ( " \n " , __func__ ) ; flow_rule_match_vlan ( rule , & match ) ; flow -> rule . itag = match . key -> vlan_id ; flow -> rule . itag_m = match . mask -> vlan_id ; } if ( flow_rule_match_key ( rule , FLOW_DISSECTOR_KEY_IPV4_ADDRS ) ) { struct flow_match_ipv4_addrs match ; pr_debug ( " \n " , __func__ ) ; flow_rule_match_ipv4_addrs ( rule , & match ) ; flow -> rule . is_ipv6 = false ; flow -> rule . dip = match . key -> dst ; flow -> rule . dip_m = match . mask -> dst ; flow -> rule . sip = match . key -> src ; flow -> rule . sip_m = match . mask -> src ; } else if ( flow_rule_match_key ( rule , FLOW_DISSECTOR_KEY_IPV6_ADDRS ) ) { struct flow_match_ipv6_addrs match ; pr_debug ( " \n " , __func__ ) ; flow -> rule . is_ipv6 = true ; flow_rule_match_ipv6_addrs ( rule , & match ) ; flow -> rule . dip6 = match . key -> dst ; flow -> rule . dip6_m = match . mask -> dst ; flow -> rule . sip6 = match . key -> src ; flow -> rule . sip6_m = match . mask -> src ; } if ( flow_rule_match_key ( rule , FLOW_DISSECTOR_KEY_PORTS ) ) { struct flow_match_ports match ; pr_debug ( " \n " , __func__ ) ; flow_rule_match_ports ( rule , & match ) ; flow -> rule . dport = match . key -> dst ; flow -> rule . dport_m = match . mask -> dst ; flow -> rule . sport = match . key -> src ; flow -> rule . sport_m = match . mask -> src ; } return 0 ; }
Parse the flow rule for the matching conditions
Parse the flow rule for the matching conditions
/* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */ // TODO: What about match.key->vlan_priority ? // TODO: ICMP