Message ID | 20200506074900.28529-5-xiaoliang.yang_1@nxp.com |
---|---|
State | Changes Requested |
Delegated to: | David Miller |
Headers | show |
Series | net: ocelot: VCAP IS1 and ES0 support | expand |
Hi Xiaoliang, On 06.05.2020 15:48, Xiaoliang Yang wrote: >VCAP IS1 is a VCAP module which can filter MAC, IP, VLAN, protocol, and >TCP/UDP ports keys, and do Qos and VLAN retag actions. >This patch added VCAP IS1 support in ocelot ace driver, which can supports >vlan modify action of tc filter. >Usage: > tc qdisc add dev swp0 ingress > tc filter add dev swp0 protocol 802.1Q parent ffff: flower \ > skip_sw vlan_id 1 vlan_prio 1 action vlan modify id 2 priority 2 I skimmed skimmed through the patch serie, and the way I understood it is that you look at the action, and if it is a VLAN operation, then you put it in IS1 and if it is one of the other then put it in IS2. This is how the HW is designed - I'm aware of that. But how will this work if you have 2 rules, 1 modifying the VLAN and another rule dropping certain packets? The SW model have these two rules in the same table, and can stop process at the first match. SW will do the action of the first frame matching. The HW will how-ever do both, as they are in independent TCAMs. If we want to enable all the TCAM lookups in Ocelot/Felix, then we need to find a way where we will get the same results when doing the operation in HW and in SW. /Allan
Hi Allan, On Wed, 6 May 2020 at 12:45, Allan W. Nielsen <allan.nielsen@microchip.com> wrote: > > Hi Xiaoliang, > > On 06.05.2020 15:48, Xiaoliang Yang wrote: > >VCAP IS1 is a VCAP module which can filter MAC, IP, VLAN, protocol, and > >TCP/UDP ports keys, and do Qos and VLAN retag actions. > >This patch added VCAP IS1 support in ocelot ace driver, which can supports > >vlan modify action of tc filter. > >Usage: > > tc qdisc add dev swp0 ingress > > tc filter add dev swp0 protocol 802.1Q parent ffff: flower \ > > skip_sw vlan_id 1 vlan_prio 1 action vlan modify id 2 priority 2 > I skimmed skimmed through the patch serie, and the way I understood it > is that you look at the action, and if it is a VLAN operation, then you > put it in IS1 and if it is one of the other then put it in IS2. > > This is how the HW is designed - I'm aware of that. > > But how will this work if you have 2 rules, 1 modifying the VLAN and > another rule dropping certain packets? > At the moment, the driver does not support more than 1 action. We might need to change that, but we can still install more filters with the same key and still be fine (see more below). When there is more than 1 action, the IS1 stuff will be combined into a single rule programmed into IS1, and the IS2 stuff will be combined into a single new rule with the same keys installed into VCAP IS2. Would that not work? > The SW model have these two rules in the same table, and can stop > process at the first match. SW will do the action of the first frame > matching. > Actually I think this is an incorrect assumption - software stops at the first action only if told to do so. Let me copy-paste a text from a different email thread. " Thank you for the good discussion today. I think the key talking points were: - How to express with tc filters the fact that some actions are executed by different hardware pipelines than others (VCAP IS1: vlan retagging and QoS classification, VCAP IS2: trap, drop, police), and that those pipelines can be completely independent, as well as chained via a policy - How to express the fact that VCAP IS1 can perform up to 3 parallel lookups (and VCAP IS2 can perform 2 lookups) per frame with potentially different key types and different actions. I am trying to take a different (top-down) approach than Allan, which is to try to express the capabilities that we are interested in offloading to Ocelot/Felix as software (skip_hw) tc filters first. It was said during the call that flow classification stops at the first action that matches a frame, which would prevent us from adding actions for the VCAP IS1 in the same chain as actions for the VCAP IS2. Actually it seems that it is possible to specify to the flow classifier what to do after each individual action, as can be seen in the man page of tc-actions (http://man7.org/linux/man-pages/man8/tc-actions.8.html): CONTROL The CONTROL indicates how tc should proceed after executing the action. Any of the following are valid: reclassify Restart the classifiction by jumping back to the first filter attached to the action's parent. pipe Continue with the next action. This is the default control. drop Drop the packed without running any further actions. continue Continue the classification with the next filter. pass Return to the calling qdisc for packet processing, and end classification of this packet. In the above description, it says that "pipe" is the default action control. My experience does not seem to coincide with that. I wrote this quick list of software filters: tc qdisc add dev swp0 clsact # IS1 tc filter add dev swp0 ingress protocol ip flower skip_hw src_ip 192.168.1.1 hw_tc 5 tc filter add dev swp0 ingress protocol all flower skip_hw action vlan push id 3 tc filter add dev swp0 egress protocol 802.1Q flower skip_hw action vlan pop # IS2 swp0_mac=$(ip link show dev swp0 | awk '/link\/ether/ {print $2}') tc filter add dev swp0 ingress protocol all flower skip_hw dst_mac ${swp0_mac} action police rate 37Mbit burst 64k ip link add link swp0 name swp0.3 type vlan id 3 && ip link set dev swp0.3 up which would permit me to terminate IP traffic on the swp0.3 VLAN sub-interface, over which I ran an iperf3 test. The traffic _was_ successfully rate limited at 37 Mbps, _and_ retagged, but I got a lot of these errors coming from tcf_classify: [ 321.100883] net_ratelimit: 150766 callbacks suppressed [ 321.100896] 0: reclassify loop, rule prio 0, protocol 03 [ 321.112613] 0: reclassify loop, rule prio 0, protocol 03 [ 321.118625] 0: reclassify loop, rule prio 0, protocol 03 [ 321.124575] 0: reclassify loop, rule prio 0, protocol 03 [ 321.130566] 0: reclassify loop, rule prio 0, protocol 03 [ 321.136630] 0: reclassify loop, rule prio 0, protocol 03 [ 321.142610] 0: reclassify loop, rule prio 0, protocol 03 [ 321.148603] 0: reclassify loop, rule prio 0, protocol 03 [ 321.154625] 0: reclassify loop, rule prio 0, protocol 03 [ 321.160569] 0: reclassify loop, rule prio 0, protocol 03 And looking at the rules themselves: tc -s filter show dev swp0 ingress filter protocol all pref 49150 flower chain 0 filter protocol all pref 49150 flower chain 0 handle 0x1 dst_mac 26:cc:e4:73:9f:9b skip_hw not_in_hw action order 1: police 0x1 rate 37Mbit burst 64Kb mtu 2Kb action reclassify overhead 0b ref 1 bind 1 installed 20 sec used 6 sec Action statistics: Sent 1994574813 bytes 1351356 pkt (dropped 0, overlimits 1319959 requeues 0) backlog 0b 0p requeues 0 filter protocol all pref 49151 flower chain 0 filter protocol all pref 49151 flower chain 0 handle 0x1 skip_hw not_in_hw action order 1: vlan push id 3 protocol 802.1Q priority 0 pipe index 1 ref 1 bind 1 installed 20 sec used 0 sec Action statistics: Sent 1263 bytes 21 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 filter protocol ip pref 49152 flower chain 0 filter protocol ip pref 49152 flower chain 0 handle 0x1 hw_tc 5 eth_type ipv4 src_ip 192.168.1.1 skip_hw not_in_hw basically the "vlan push" rule matches on way less packets than I was expecting, and the default control for the police action is to reclassify, not to pipe. I think this is an odd choice for a default value, but it looks like I can specify the police rule like this (using conform-exceed): tc filter add dev swp0 ingress protocol all flower skip_hw dst_mac ${swp0_mac} action police rate 37Mbit burst 64k conform-exceed drop/pipe Basically the idea I want to transmit is that the impression we had during the call does not seem to hold true. The default action control is "pipe" (well, it's "almost" default), which has the effect of going through all rules and not just through the first one that matches (that would be the "pass" control). So in principle I don't see why we couldn't model the actions that require VLAN retagging or QoS classification as lookups in IS1 (ES0 might also need to be involved in the retagging case, I am not 100% sure how the egress rewriter is involved in the retagging process, but it seems like it is), and the actions that require dropping, trapping or policing as lookups in IS2. I am not sure that chains would be necessary, nor that we could use them anyway (given that we can't make a chain template based on action types). As for the other point (multiple TCAM lookups in the same block), I think some concrete examples would definitely help. The example of supporting matches on src_mac and src_ip simultaneously is a valid one, but it can be dealt with just privately by the driver. Looking for concrete examples where that would not be enough. Another item I would like to bring up is how to perform QoS classification. In my example I used the "hw_tc" action from tc-flower, but not being offloaded, I couldn't test it. Is this how it should be done? Is there an equivalent to hw_tc in tc-matchall and in tc-u32? We might need them there too. " > The HW will how-ever do both, as they are in independent TCAMs. > > If we want to enable all the TCAM lookups in Ocelot/Felix, then we need > to find a way where we will get the same results when doing the > operation in HW and in SW. > > /Allan > Thanks, -Vladimir
Hi Vladimir, On 06.05.2020 13:53, Vladimir Oltean wrote: >On Wed, 6 May 2020 at 12:45, Allan W. Nielsen ><allan.nielsen@microchip.com> wrote: >> >> Hi Xiaoliang, >> >> On 06.05.2020 15:48, Xiaoliang Yang wrote: >> >VCAP IS1 is a VCAP module which can filter MAC, IP, VLAN, protocol, and >> >TCP/UDP ports keys, and do Qos and VLAN retag actions. >> >This patch added VCAP IS1 support in ocelot ace driver, which can supports >> >vlan modify action of tc filter. >> >Usage: >> > tc qdisc add dev swp0 ingress >> > tc filter add dev swp0 protocol 802.1Q parent ffff: flower \ >> > skip_sw vlan_id 1 vlan_prio 1 action vlan modify id 2 priority 2 >> I skimmed skimmed through the patch serie, and the way I understood it >> is that you look at the action, and if it is a VLAN operation, then you >> put it in IS1 and if it is one of the other then put it in IS2. >> >> This is how the HW is designed - I'm aware of that. >> >> But how will this work if you have 2 rules, 1 modifying the VLAN and >> another rule dropping certain packets? >> > >At the moment, the driver does not support more than 1 action. We >might need to change that, but we can still install more filters with >the same key and still be fine (see more below). When there is more >than 1 action, the IS1 stuff will be combined into a single rule >programmed into IS1, and the IS2 stuff will be combined into a single >new rule with the same keys installed into VCAP IS2. Would that not >work? > >> The SW model have these two rules in the same table, and can stop >> process at the first match. SW will do the action of the first frame >> matching. >> > >Actually I think this is an incorrect assumption - software stops at >the first action only if told to do so. Let me copy-paste a text from >a different email thread. I'm still not able to see how this proposal will give us the same behavioral in SW and in HW. A simple example: tc qdisc add dev enp0s3 ingress tc filter add dev enp0s3 protocol 802.1Q parent ffff: \ prio 10 flower vlan_id 5 action vlan modify id 10 tc filter add dev enp0s3 protocol 802.1Q parent ffff: \ prio 20 flower src_mac 00:00:00:00:00:08 action drop We can then inject a frame with VID 5 and smac ::08: $ ef tx tap0 eth smac 00:00:00:00:00:08 ctag vid 5 We can then check the filter and see that it only hit the first rule: $ tc -s filter show dev enp0s3 ingress filter protocol 802.1Q pref 10 flower chain 0 filter protocol 802.1Q pref 10 flower chain 0 handle 0x1 vlan_id 5 not_in_hw action order 1: vlan modify id 10 protocol 802.1Q priority 0 pipe index 1 ref 1 bind 1 installed 19 sec used 6 sec Action statistics: Sent 42 bytes 1 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 filter protocol 802.1Q pref 20 flower chain 0 filter protocol 802.1Q pref 20 flower chain 0 handle 0x1 src_mac 00:00:00:00:00:08 not_in_hw action order 1: gact action drop random type none pass val 0 index 1 ref 1 bind 1 installed 11 sec used 11 sec Action statistics: Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 If this was done with the proposed HW offload, then both rules would have been hit and we would have a different behavioral. This can be fixed by adding the "continue" action to the first rule: tc filter add dev enp0s3 protocol 802.1Q parent ffff: \ prio 10 flower vlan_id 5 action vlan modify id 10 continue tc filter add dev enp0s3 protocol 802.1Q parent ffff: \ prio 20 flower src_mac 00:00:00:00:00:08 action drop But that would again break if we add 2 rules manipulating the VLAN (as the HW does not continue with in a single TCAM). My point is: I do not think we can hide the fact that this is done in independent TCAMs in the silicon. I think it is possible to do this with the chain feature (even though it is not a perfect match), but it would require more analysis. /Allan
Hi Allan, > Hi Vladimir, > > On 06.05.2020 13:53, Vladimir Oltean wrote: [snip] > >At the moment, the driver does not support more than 1 action. We might > >need to change that, but we can still install more filters with the > >same key and still be fine (see more below). When there is more than 1 > >action, the IS1 stuff will be combined into a single rule programmed > >into IS1, and the IS2 stuff will be combined into a single new rule > >with the same keys installed into VCAP IS2. Would that not work? > > > >> The SW model have these two rules in the same table, and can stop > >> process at the first match. SW will do the action of the first frame > >> matching. > >> > > > >Actually I think this is an incorrect assumption - software stops at > >the first action only if told to do so. Let me copy-paste a text from a > >different email thread. > > I'm still not able to see how this proposal will give us the same behavioral in SW and in HW. > > A simple example: > > tc qdisc add dev enp0s3 ingress > tc filter add dev enp0s3 protocol 802.1Q parent ffff: \ > prio 10 flower vlan_id 5 action vlan modify id 10 tc filter add dev enp0s3 protocol 802.1Q parent ffff: \ > prio 20 flower src_mac 00:00:00:00:00:08 action drop > > We can then inject a frame with VID 5 and smac ::08: > $ ef tx tap0 eth smac 00:00:00:00:00:08 ctag vid 5 > > We can then check the filter and see that it only hit the first rule: > > $ tc -s filter show dev enp0s3 ingress > filter protocol 802.1Q pref 10 flower chain 0 filter protocol 802.1Q pref 10 flower chain 0 handle 0x1 > vlan_id 5 > not_in_hw > action order 1: vlan modify id 10 protocol 802.1Q priority 0 pipe > index 1 ref 1 bind 1 installed 19 sec used 6 sec > Action statistics: > Sent 42 bytes 1 pkt (dropped 0, overlimits 0 requeues 0) > backlog 0b 0p requeues 0 > > filter protocol 802.1Q pref 20 flower chain 0 filter protocol 802.1Q pref 20 flower chain 0 handle 0x1 > src_mac 00:00:00:00:00:08 > not_in_hw > action order 1: gact action drop > random type none pass val 0 > index 1 ref 1 bind 1 installed 11 sec used 11 sec > Action statistics: > Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) > backlog 0b 0p requeues 0 > > If this was done with the proposed HW offload, then both rules would have been hit and we would have a different behavioral. > > This can be fixed by adding the "continue" action to the first rule: > tc filter add dev enp0s3 protocol 802.1Q parent ffff: \ > prio 10 flower vlan_id 5 action vlan modify id 10 continue tc filter add dev enp0s3 protocol 802.1Q parent ffff: \ > prio 20 flower src_mac 00:00:00:00:00:08 action drop > > But that would again break if we add 2 rules manipulating the VLAN (as the HW does not continue with in a single TCAM). > > My point is: I do not think we can hide the fact that this is done in independent TCAMs in the silicon. > > I think it is possible to do this with the chain feature (even though it is not a perfect match), but it would require more analysis. > > /Allan Do you mean it's better to set vlan modify filters in a different chain, and write the filter entries with a same chain in the same VCAP TCAM? For example: tc filter add dev enp0s3 protocol 802.1Q chain 11 parent ffff: prio 10 flower skip_sw vlan_id 5 action vlan modify id 10 tc filter add dev enp0s3 protocol 802.1Q chain 22 parent ffff: prio 20 flower skip_sw src_mac 00:00:00:00:00:08 action drop for this usage, we only need to ensure a chain corresponding to a VCAP in ocelot ace driver. I'm not sure is my understanding right? regards, Xiaoliang
On 07.05.2020 11:23, Xiaoliang Yang wrote: >EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe > >Hi Allan, > > >> Hi Vladimir, >> >> On 06.05.2020 13:53, Vladimir Oltean wrote: >[snip] >> >At the moment, the driver does not support more than 1 action. We might >> >need to change that, but we can still install more filters with the >> >same key and still be fine (see more below). When there is more than 1 >> >action, the IS1 stuff will be combined into a single rule programmed >> >into IS1, and the IS2 stuff will be combined into a single new rule >> >with the same keys installed into VCAP IS2. Would that not work? >> > >> >> The SW model have these two rules in the same table, and can stop >> >> process at the first match. SW will do the action of the first frame >> >> matching. >> >> >> > >> >Actually I think this is an incorrect assumption - software stops at >> >the first action only if told to do so. Let me copy-paste a text from a >> >different email thread. >> >> I'm still not able to see how this proposal will give us the same behavioral in SW and in HW. >> >> A simple example: >> >> tc qdisc add dev enp0s3 ingress >> tc filter add dev enp0s3 protocol 802.1Q parent ffff: \ >> prio 10 flower vlan_id 5 action vlan modify id 10 tc filter add dev enp0s3 protocol 802.1Q parent ffff: \ >> prio 20 flower src_mac 00:00:00:00:00:08 action drop >> >> We can then inject a frame with VID 5 and smac ::08: >> $ ef tx tap0 eth smac 00:00:00:00:00:08 ctag vid 5 >> >> We can then check the filter and see that it only hit the first rule: >> >> $ tc -s filter show dev enp0s3 ingress >> filter protocol 802.1Q pref 10 flower chain 0 filter protocol 802.1Q pref 10 flower chain 0 handle 0x1 >> vlan_id 5 >> not_in_hw >> action order 1: vlan modify id 10 protocol 802.1Q priority 0 pipe >> index 1 ref 1 bind 1 installed 19 sec used 6 sec >> Action statistics: >> Sent 42 bytes 1 pkt (dropped 0, overlimits 0 requeues 0) >> backlog 0b 0p requeues 0 >> >> filter protocol 802.1Q pref 20 flower chain 0 filter protocol 802.1Q pref 20 flower chain 0 handle 0x1 >> src_mac 00:00:00:00:00:08 >> not_in_hw >> action order 1: gact action drop >> random type none pass val 0 >> index 1 ref 1 bind 1 installed 11 sec used 11 sec >> Action statistics: >> Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) >> backlog 0b 0p requeues 0 >> >> If this was done with the proposed HW offload, then both rules would have been hit and we would have a different behavioral. >> >> This can be fixed by adding the "continue" action to the first rule: > >> tc filter add dev enp0s3 protocol 802.1Q parent ffff: \ >> prio 10 flower vlan_id 5 action vlan modify id 10 continue tc filter add dev enp0s3 protocol 802.1Q parent ffff: \ >> prio 20 flower src_mac 00:00:00:00:00:08 action drop >> >> But that would again break if we add 2 rules manipulating the VLAN (as the HW does not continue with in a single TCAM). >> >> My point is: I do not think we can hide the fact that this is done in independent TCAMs in the silicon. >> >> I think it is possible to do this with the chain feature (even though it is not a perfect match), but it would require more analysis. >> >> /Allan > >Do you mean it's better to set vlan modify filters in a different chain, and write the filter entries with a same chain in the same VCAP TCAM? >For example: > tc filter add dev enp0s3 protocol 802.1Q chain 11 parent ffff: prio 10 flower skip_sw vlan_id 5 action vlan modify id 10 > tc filter add dev enp0s3 protocol 802.1Q chain 22 parent ffff: prio 20 flower skip_sw src_mac 00:00:00:00:00:08 action drop >for this usage, we only need to ensure a chain corresponding to a VCAP in ocelot ace driver. I'm not sure is my understanding right? I still have not found a satisfying solution to this. As I understand the chains, they require the "goto" action to be used to tie them together. We could use that to represent a single lookup in is1 and link that to a lookup in is2. Not sure if we should, it will also require (non-backwards compatible) changes in how the existing IS2 support is working. Again, I do not have the answer (I'm also looking for it), but I think we need something where it is clear to the user that this end up in different lists. /Allan
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 3b37c5f41fca..1f5edabf5fd2 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -13,6 +13,8 @@ #define VSC9959_VCAP_IS2_CNT 1024 #define VSC9959_VCAP_IS2_ENTRY_WIDTH 376 #define VSC9959_VCAP_PORT_CNT 6 +#define VSC9959_VCAP_IS1_CNT 256 +#define VSC9959_VCAP_IS1_ENTRY_WIDTH 376 /* TODO: should find a better place for these */ #define USXGMII_BMCR_RESET BIT(15) @@ -332,6 +334,7 @@ static const u32 *vsc9959_regmap[] = { [QSYS] = vsc9959_qsys_regmap, [REW] = vsc9959_rew_regmap, [SYS] = vsc9959_sys_regmap, + [S1] = vsc9959_vcap_regmap, [S2] = vsc9959_vcap_regmap, [PTP] = vsc9959_ptp_regmap, [GCB] = vsc9959_gcb_regmap, @@ -366,6 +369,11 @@ static struct resource vsc9959_target_io_res[] = { .end = 0x001ffff, .name = "sys", }, + [S1] = { + .start = 0x0050000, + .end = 0x00503ff, + .name = "s1", + }, [S2] = { .start = 0x0060000, .end = 0x00603ff, @@ -556,6 +564,80 @@ static const struct ocelot_stat_layout vsc9959_stats_layout[] = { { .offset = 0x111, .name = "drop_green_prio_7", }, }; +struct vcap_field vsc9959_vcap_is1_keys[] = { + [VCAP_IS1_HK_TYPE] = { 0, 1}, + [VCAP_IS1_HK_LOOKUP] = { 1, 2}, + [VCAP_IS1_HK_IGR_PORT_MASK] = { 3, 7}, + [VCAP_IS1_HK_RSV] = { 10, 9}, + [VCAP_IS1_HK_OAM_Y1731] = { 19, 1}, + [VCAP_IS1_HK_L2_MC] = { 20, 1}, + [VCAP_IS1_HK_L2_BC] = { 21, 1}, + [VCAP_IS1_HK_IP_MC] = { 22, 1}, + [VCAP_IS1_HK_VLAN_TAGGED] = { 23, 1}, + [VCAP_IS1_HK_VLAN_DBL_TAGGED] = { 24, 1}, + [VCAP_IS1_HK_TPID] = { 25, 1}, + [VCAP_IS1_HK_VID] = { 26, 12}, + [VCAP_IS1_HK_DEI] = { 38, 1}, + [VCAP_IS1_HK_PCP] = { 39, 3}, + /* Specific Fields for IS1 Half Key S1_NORMAL */ + [VCAP_IS1_HK_L2_SMAC] = { 42, 48}, + [VCAP_IS1_HK_ETYPE_LEN] = { 90, 1}, + [VCAP_IS1_HK_ETYPE] = { 91, 16}, + [VCAP_IS1_HK_IP_SNAP] = {107, 1}, + [VCAP_IS1_HK_IP4] = {108, 1}, + /* Layer-3 Information */ + [VCAP_IS1_HK_L3_FRAGMENT] = {109, 1}, + [VCAP_IS1_HK_L3_FRAG_OFS_GT0] = {110, 1}, + [VCAP_IS1_HK_L3_OPTIONS] = {111, 1}, + [VCAP_IS1_HK_L3_DSCP] = {112, 6}, + [VCAP_IS1_HK_L3_IP4_SIP] = {118, 32}, + /* Layer-4 Information */ + [VCAP_IS1_HK_TCP_UDP] = {150, 1}, + [VCAP_IS1_HK_TCP] = {151, 1}, + [VCAP_IS1_HK_L4_SPORT] = {152, 16}, + [VCAP_IS1_HK_L4_RNG] = {168, 8}, + /* Specific Fields for IS1 Half Key S1_5TUPLE_IP4 */ + [VCAP_IS1_HK_IP4_INNER_TPID] = { 42, 1}, + [VCAP_IS1_HK_IP4_INNER_VID] = { 43, 12}, + [VCAP_IS1_HK_IP4_INNER_DEI] = { 55, 1}, + [VCAP_IS1_HK_IP4_INNER_PCP] = { 56, 3}, + [VCAP_IS1_HK_IP4_IP4] = { 59, 1}, + [VCAP_IS1_HK_IP4_L3_FRAGMENT] = { 60, 1}, + [VCAP_IS1_HK_IP4_L3_FRAG_OFS_GT0] = { 61, 1}, + [VCAP_IS1_HK_IP4_L3_OPTIONS] = { 62, 1}, + [VCAP_IS1_HK_IP4_L3_DSCP] = { 63, 6}, + [VCAP_IS1_HK_IP4_L3_IP4_DIP] = { 69, 32}, + [VCAP_IS1_HK_IP4_L3_IP4_SIP] = {101, 32}, + [VCAP_IS1_HK_IP4_L3_PROTO] = {133, 8}, + [VCAP_IS1_HK_IP4_TCP_UDP] = {141, 1}, + [VCAP_IS1_HK_IP4_TCP] = {142, 1}, + [VCAP_IS1_HK_IP4_L4_RNG] = {143, 8}, + [VCAP_IS1_HK_IP4_IP_PAYLOAD_S1_5TUPLE] = {151, 32}, +}; + +struct vcap_field vsc9959_vcap_is1_actions[] = { + [VCAP_IS1_ACT_DSCP_ENA] = { 0, 1}, + [VCAP_IS1_ACT_DSCP_VAL] = { 1, 6}, + [VCAP_IS1_ACT_QOS_ENA] = { 7, 1}, + [VCAP_IS1_ACT_QOS_VAL] = { 8, 3}, + [VCAP_IS1_ACT_DP_ENA] = { 11, 1}, + [VCAP_IS1_ACT_DP_VAL] = { 12, 1}, + [VCAP_IS1_ACT_PAG_OVERRIDE_MASK] = { 13, 8}, + [VCAP_IS1_ACT_PAG_VAL] = { 21, 8}, + [VCAP_IS1_ACT_RSV] = { 29, 9}, + [VCAP_IS1_ACT_VID_REPLACE_ENA] = { 38, 1}, + [VCAP_IS1_ACT_VID_ADD_VAL] = { 39, 12}, + [VCAP_IS1_ACT_FID_SEL] = { 51, 2}, + [VCAP_IS1_ACT_FID_VAL] = { 53, 13}, + [VCAP_IS1_ACT_PCP_DEI_ENA] = { 66, 1}, + [VCAP_IS1_ACT_PCP_VAL] = { 67, 3}, + [VCAP_IS1_ACT_DEI_VAL] = { 70, 1}, + [VCAP_IS1_ACT_VLAN_POP_CNT_ENA] = { 71, 1}, + [VCAP_IS1_ACT_VLAN_POP_CNT] = { 72, 2}, + [VCAP_IS1_ACT_CUSTOM_ACE_TYPE_ENA] = { 74, 4}, + [VCAP_IS1_ACT_HIT_STICKY] = { 78, 1}, +}; + struct vcap_field vsc9959_vcap_is2_keys[] = { /* Common: 41 bits */ [VCAP_IS2_TYPE] = { 0, 4}, @@ -655,6 +737,26 @@ struct vcap_field vsc9959_vcap_is2_actions[] = { }; static const struct vcap_props vsc9959_vcap_props[] = { + [VCAP_IS1] = { + .tg_width = 2, + .sw_count = 4, + .entry_count = VSC9959_VCAP_IS1_CNT, + .entry_width = VSC9959_VCAP_IS1_ENTRY_WIDTH, + .action_count = VSC9959_VCAP_IS1_CNT + 1, + .action_width = 312, + .action_type_width = 0, + .action_table = { + [IS1_ACTION_TYPE_NORMAL] = { + .width = 78, + .count = 4 + }, + }, + .counter_words = 1, + .counter_width = 4, + .target = S1, + .keys = vsc9959_vcap_is1_keys, + .actions = vsc9959_vcap_is1_actions, + }, [VCAP_IS2] = { .tg_width = 2, .sw_count = 4, diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index a2b9b85612a4..2fa22801bc67 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -136,6 +136,13 @@ static void ocelot_vcap_enable(struct ocelot *ocelot, int port) ocelot_write_gix(ocelot, ANA_PORT_VCAP_S2_CFG_S2_ENA | ANA_PORT_VCAP_S2_CFG_S2_IP6_CFG(0xa), ANA_PORT_VCAP_S2_CFG, port); + + ocelot_write_gix(ocelot, ANA_PORT_VCAP_CFG_S1_ENA, + ANA_PORT_VCAP_CFG, port); + ocelot_write_gix(ocelot, + ANA_PORT_VCAP_S1_KEY_CFG_S1_KEY_IP6_CFG(2) | + ANA_PORT_VCAP_S1_KEY_CFG_S1_KEY_IP4_CFG(2), + ANA_PORT_VCAP_S1_KEY_CFG, port); } static inline u32 ocelot_vlant_read_vlanaccess(struct ocelot *ocelot) diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c index 29d61b89b73a..0f0fc709113b 100644 --- a/drivers/net/ethernet/mscc/ocelot_ace.c +++ b/drivers/net/ethernet/mscc/ocelot_ace.c @@ -341,6 +341,8 @@ static void is2_action_set(struct ocelot *ocelot, struct vcap_data *data, vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, 0); vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, 0); break; + default: + break; } } @@ -643,6 +645,195 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, vcap_row_cmd(ocelot, vcap, row, VCAP_CMD_WRITE, VCAP_SEL_ALL); } +static void is1_action_set(struct ocelot *ocelot, struct vcap_data *data, + struct ocelot_ace_rule *ace) +{ + const struct vcap_props *vcap = &ocelot->vcap[VCAP_IS1]; + + switch (ace->action) { + case OCELOT_ACL_ACTION_VLAN_MODIFY: + vcap_action_set(vcap, data, VCAP_IS1_ACT_QOS_ENA, 1); + vcap_action_set(vcap, data, VCAP_IS1_ACT_QOS_VAL, + ace->vlan_modify.pcp); + vcap_action_set(vcap, data, VCAP_IS1_ACT_VID_REPLACE_ENA, 1); + vcap_action_set(vcap, data, VCAP_IS1_ACT_VID_ADD_VAL, + ace->vlan_modify.vid); + vcap_action_set(vcap, data, VCAP_IS1_ACT_PCP_DEI_ENA, 1); + vcap_action_set(vcap, data, VCAP_IS1_ACT_PCP_VAL, + ace->vlan_modify.pcp); + vcap_action_set(vcap, data, VCAP_IS1_ACT_DEI_VAL, + ace->vlan_modify.dei); + break; + default: + break; + } +} + +static void is1_entry_set(struct ocelot *ocelot, int ix, + struct ocelot_ace_rule *ace) +{ + const struct vcap_props *vcap = &ocelot->vcap[VCAP_IS1]; + u32 val, msk, type, i; + struct ocelot_ace_vlan *tag = &ace->vlan; + struct ocelot_vcap_u64 payload; + struct vcap_data data; + int row = ix / 2; + + memset(&payload, 0, sizeof(payload)); + memset(&data, 0, sizeof(data)); + + /* Read row */ + vcap_row_cmd(ocelot, vcap, row, VCAP_CMD_READ, VCAP_SEL_ALL); + vcap_cache2entry(ocelot, vcap, &data); + vcap_cache2action(ocelot, vcap, &data); + + data.tg_sw = VCAP_TG_HALF; + data.type = IS1_ACTION_TYPE_NORMAL; + vcap_data_offset_get(vcap, &data, ix); + data.tg = (data.tg & ~data.tg_mask); + if (ace->prio != 0) + data.tg |= data.tg_value; + + vcap_key_set(vcap, &data, VCAP_IS1_HK_IGR_PORT_MASK, 0, + ~ace->ingress_port_mask); + vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_L2_MC, ace->dmac_mc); + vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_L2_BC, ace->dmac_bc); + vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_VLAN_TAGGED, tag->tagged); + vcap_key_set(vcap, &data, VCAP_IS1_HK_VID, + tag->vid.value, tag->vid.mask); + vcap_key_set(vcap, &data, VCAP_IS1_HK_PCP, + tag->pcp.value[0], tag->pcp.mask[0]); + type = IS1_TYPE_S1_NORMAL; + + switch (ace->type) { + case OCELOT_ACE_TYPE_ETYPE: { + struct ocelot_ace_frame_etype *etype = &ace->frame.etype; + + type = IS1_TYPE_S1_NORMAL; + vcap_key_bytes_set(vcap, &data, VCAP_IS1_HK_L2_SMAC, + etype->smac.value, etype->smac.mask); + vcap_key_bytes_set(vcap, &data, VCAP_IS1_HK_ETYPE, + etype->etype.value, etype->etype.mask); + break; + } + case OCELOT_ACE_TYPE_IPV4: + case OCELOT_ACE_TYPE_IPV6: { + enum ocelot_vcap_bit sip_eq_dip, sport_eq_dport; + enum ocelot_vcap_bit seq_zero, tcp; + enum ocelot_vcap_bit ttl, fragment, options; + enum ocelot_vcap_bit tcp_ack, tcp_urg; + enum ocelot_vcap_bit tcp_fin, tcp_syn, tcp_rst, tcp_psh; + struct ocelot_ace_frame_ipv4 *ipv4 = NULL; + struct ocelot_ace_frame_ipv6 *ipv6 = NULL; + struct ocelot_vcap_udp_tcp *sport, *dport; + struct ocelot_vcap_ipv4 sip, dip; + struct ocelot_vcap_u8 proto, ds; + struct ocelot_vcap_u48 *ip_data; + struct ocelot_vcap_u32 port; + + type = IS1_TYPE_S1_5TUPLE_IP4; + if (ace->type == OCELOT_ACE_TYPE_IPV4) { + ipv4 = &ace->frame.ipv4; + ttl = ipv4->ttl; + fragment = ipv4->fragment; + options = ipv4->options; + proto = ipv4->proto; + ds = ipv4->ds; + ip_data = &ipv4->data; + sip = ipv4->sip; + dip = ipv4->dip; + sport = &ipv4->sport; + dport = &ipv4->dport; + tcp_fin = ipv4->tcp_fin; + tcp_syn = ipv4->tcp_syn; + tcp_rst = ipv4->tcp_rst; + tcp_psh = ipv4->tcp_psh; + tcp_ack = ipv4->tcp_ack; + tcp_urg = ipv4->tcp_urg; + sip_eq_dip = ipv4->sip_eq_dip; + sport_eq_dport = ipv4->sport_eq_dport; + seq_zero = ipv4->seq_zero; + } else { + ipv6 = &ace->frame.ipv6; + ttl = ipv6->ttl; + fragment = OCELOT_VCAP_BIT_ANY; + options = OCELOT_VCAP_BIT_ANY; + proto = ipv6->proto; + ds = ipv6->ds; + ip_data = &ipv6->data; + for (i = 0; i < 4; i++) { + dip.value.addr[i] = ipv6->dip.value[i]; + dip.mask.addr[i] = ipv6->dip.mask[i]; + sip.value.addr[i] = ipv6->sip.value[i]; + sip.mask.addr[i] = ipv6->sip.mask[i]; + } + sport = &ipv6->sport; + dport = &ipv6->dport; + tcp_fin = ipv6->tcp_fin; + tcp_syn = ipv6->tcp_syn; + tcp_rst = ipv6->tcp_rst; + tcp_psh = ipv6->tcp_psh; + tcp_ack = ipv6->tcp_ack; + tcp_urg = ipv6->tcp_urg; + sip_eq_dip = ipv6->sip_eq_dip; + sport_eq_dport = ipv6->sport_eq_dport; + seq_zero = ipv6->seq_zero; + } + + vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_IP4_IP4, + ipv4 ? OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0); + vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_IP4_L3_FRAGMENT, + fragment); + vcap_key_set(vcap, &data, VCAP_IS1_HK_IP4_L3_FRAG_OFS_GT0, + 0, 0); + vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_IP4_L3_OPTIONS, + options); + vcap_key_bytes_set(vcap, &data, VCAP_IS1_HK_IP4_L3_IP4_DIP, + dip.value.addr, dip.mask.addr); + vcap_key_bytes_set(vcap, &data, VCAP_IS1_HK_IP4_L3_IP4_SIP, + sip.value.addr, sip.mask.addr); + val = proto.value[0]; + msk = proto.mask[0]; + if (msk == 0xff && (val == 6 || val == 17)) { + /* UDP/TCP protocol match */ + tcp = (val == 6 ? + OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0); + vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_IP4_TCP, + tcp); + vcap_key_l4_port_set(vcap, &data, + VCAP_IS1_HK_L4_SPORT, sport); + vcap_key_set(vcap, &data, VCAP_IS1_HK_IP4_L4_RNG, + 0, 0); + port.value[0] = sport->value & 0xFF; + port.value[1] = sport->value >> 8; + port.value[2] = dport->value & 0xFF; + port.value[3] = dport->value >> 8; + port.mask[0] = sport->mask & 0xFF; + port.mask[1] = sport->mask >> 8; + port.mask[2] = dport->mask & 0xFF; + port.mask[3] = dport->mask >> 8; + vcap_key_bytes_set(vcap, &data, + VCAP_IS1_HK_IP4_IP_PAYLOAD_S1_5TUPLE, + port.value, port.mask); + } + break; + } + default: + break; + } + vcap_key_bit_set(vcap, &data, VCAP_IS1_HK_TYPE, + type ? OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0); + + is1_action_set(ocelot, &data, ace); + vcap_data_set(data.counter, data.counter_offset, + vcap->counter_width, ace->stats.pkts); + + /* Write row */ + vcap_entry2cache(ocelot, vcap, &data); + vcap_action2cache(ocelot, vcap, &data); + vcap_row_cmd(ocelot, vcap, row, VCAP_CMD_WRITE, VCAP_SEL_ALL); +} + static void vcap_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule, int ix) { @@ -667,6 +858,9 @@ static void vcap_entry_set(struct ocelot *ocelot, int ix, struct ocelot_ace_rule *ace) { switch (ace->vcap_id) { + case VCAP_IS1: + is1_entry_set(ocelot, ix, ace); + break; case VCAP_IS2: is2_entry_set(ocelot, ix, ace); break; @@ -1007,6 +1201,7 @@ int ocelot_ace_init(struct ocelot *ocelot) { struct ocelot_acl_block *block; + vcap_init(ocelot, &ocelot->vcap[VCAP_IS1]); vcap_init(ocelot, &ocelot->vcap[VCAP_IS2]); /* Create a policer that will drop the frames for the cpu. @@ -1026,7 +1221,8 @@ int ocelot_ace_init(struct ocelot *ocelot) block = &ocelot->acl_block[VCAP_IS2]; block->pol_lpr = OCELOT_POLICER_DISCARD - 1; - INIT_LIST_HEAD(&block->rules); + INIT_LIST_HEAD(&ocelot->acl_block[VCAP_IS1].rules); + INIT_LIST_HEAD(&ocelot->acl_block[VCAP_IS2].rules); return 0; } diff --git a/drivers/net/ethernet/mscc/ocelot_ace.h b/drivers/net/ethernet/mscc/ocelot_ace.h index badc883c14be..5d9c495a28f7 100644 --- a/drivers/net/ethernet/mscc/ocelot_ace.h +++ b/drivers/net/ethernet/mscc/ocelot_ace.h @@ -93,6 +93,12 @@ struct ocelot_ace_vlan { enum ocelot_vcap_bit tagged; /* Tagged/untagged frame */ }; +struct ocelot_ace_action_vlan { + u16 vid; + u8 pcp; + u8 dei; +}; + struct ocelot_ace_frame_etype { struct ocelot_vcap_u48 dmac; struct ocelot_vcap_u48 smac; @@ -158,6 +164,7 @@ struct ocelot_ace_frame_ipv4 { struct ocelot_ace_frame_ipv6 { struct ocelot_vcap_u8 proto; /* IPv6 protocol */ struct ocelot_vcap_u128 sip; /* IPv6 source (byte 0-7 ignored) */ + struct ocelot_vcap_u128 dip; /* IPv6 destination (byte 0-7 ignored) */ enum ocelot_vcap_bit ttl; /* TTL zero */ struct ocelot_vcap_u8 ds; struct ocelot_vcap_u48 data; /* Not UDP/TCP: IP data */ @@ -178,6 +185,7 @@ enum ocelot_ace_action { OCELOT_ACL_ACTION_DROP, OCELOT_ACL_ACTION_TRAP, OCELOT_ACL_ACTION_POLICE, + OCELOT_ACL_ACTION_VLAN_MODIFY, }; struct ocelot_ace_stats { @@ -200,6 +208,7 @@ struct ocelot_ace_rule { enum ocelot_vcap_bit dmac_mc; enum ocelot_vcap_bit dmac_bc; struct ocelot_ace_vlan vlan; + struct ocelot_ace_action_vlan vlan_modify; enum ocelot_ace_type type; union { diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c index 1963279cc062..f770448d7c7e 100644 --- a/drivers/net/ethernet/mscc/ocelot_flower.c +++ b/drivers/net/ethernet/mscc/ocelot_flower.c @@ -42,6 +42,12 @@ static int ocelot_flower_parse_action(struct flow_cls_offload *f, burst = rate * PSCHED_NS2TICKS(a->police.burst); ace->pol.burst = div_u64(burst, PSCHED_TICKS_PER_SEC); break; + case FLOW_ACTION_VLAN_MANGLE: + ace->vcap_id = VCAP_IS1; + ace->action = OCELOT_ACL_ACTION_VLAN_MODIFY; + ace->vlan_modify.vid = a->vlan.vid; + ace->vlan_modify.pcp = a->vlan.prio; + break; default: return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/mscc/ocelot_regs.c b/drivers/net/ethernet/mscc/ocelot_regs.c index 8cc0e0082a76..69d97cbe25d6 100644 --- a/drivers/net/ethernet/mscc/ocelot_regs.c +++ b/drivers/net/ethernet/mscc/ocelot_regs.c @@ -254,6 +254,7 @@ static const u32 *ocelot_regmap[] = { [QSYS] = ocelot_qsys_regmap, [REW] = ocelot_rew_regmap, [SYS] = ocelot_sys_regmap, + [S1] = ocelot_vcap_regmap, [S2] = ocelot_vcap_regmap, [PTP] = ocelot_ptp_regmap, }; diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index a704b5c69453..6b131cab1500 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -107,6 +107,7 @@ enum ocelot_target { QSYS, REW, SYS, + S1, S2, HSIO, PTP, diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h index da1e6b2c3ee4..6d3ed5260ad8 100644 --- a/include/soc/mscc/ocelot_vcap.h +++ b/include/soc/mscc/ocelot_vcap.h @@ -14,7 +14,7 @@ */ enum { - /* VCAP_IS1, */ + VCAP_IS1, VCAP_IS2, /* VCAP_ES0, */ VCAP_CORE_MAX, @@ -265,4 +265,95 @@ enum vcap_is2_action_field { VCAP_IS2_ACT_HIT_CNT, }; +/* ================================================================= + * VCAP IS1 + * ================================================================= + */ + +/* IS1 half key types */ +#define IS1_TYPE_S1_NORMAL 0 +#define IS1_TYPE_S1_5TUPLE_IP4 1 + +/* IS1 full key types */ +#define IS1_TYPE_S1_NORMAL_IP6 0 +#define IS1_TYPE_S1_7TUPLE 1 +#define IS2_TYPE_S1_5TUPLE_IP6 2 + +enum { + IS1_ACTION_TYPE_NORMAL, + IS1_ACTION_TYPE_MAX, +}; + +enum vcap_is1_half_key_field { + VCAP_IS1_HK_TYPE, + VCAP_IS1_HK_LOOKUP, + VCAP_IS1_HK_IGR_PORT_MASK, + VCAP_IS1_HK_RSV, + VCAP_IS1_HK_OAM_Y1731, + VCAP_IS1_HK_L2_MC, + VCAP_IS1_HK_L2_BC, + VCAP_IS1_HK_IP_MC, + VCAP_IS1_HK_VLAN_TAGGED, + VCAP_IS1_HK_VLAN_DBL_TAGGED, + VCAP_IS1_HK_TPID, + VCAP_IS1_HK_VID, + VCAP_IS1_HK_DEI, + VCAP_IS1_HK_PCP, + /* Specific Fields for IS1 Half Key S1_NORMAL */ + VCAP_IS1_HK_L2_SMAC, + VCAP_IS1_HK_ETYPE_LEN, + VCAP_IS1_HK_ETYPE, + VCAP_IS1_HK_IP_SNAP, + VCAP_IS1_HK_IP4, + VCAP_IS1_HK_L3_FRAGMENT, + VCAP_IS1_HK_L3_FRAG_OFS_GT0, + VCAP_IS1_HK_L3_OPTIONS, + VCAP_IS1_HK_L3_DSCP, + VCAP_IS1_HK_L3_IP4_SIP, + VCAP_IS1_HK_TCP_UDP, + VCAP_IS1_HK_TCP, + VCAP_IS1_HK_L4_SPORT, + VCAP_IS1_HK_L4_RNG, + /* Specific Fields for IS1 Half Key S1_5TUPLE_IP4 */ + VCAP_IS1_HK_IP4_INNER_TPID, + VCAP_IS1_HK_IP4_INNER_VID, + VCAP_IS1_HK_IP4_INNER_DEI, + VCAP_IS1_HK_IP4_INNER_PCP, + VCAP_IS1_HK_IP4_IP4, + VCAP_IS1_HK_IP4_L3_FRAGMENT, + VCAP_IS1_HK_IP4_L3_FRAG_OFS_GT0, + VCAP_IS1_HK_IP4_L3_OPTIONS, + VCAP_IS1_HK_IP4_L3_DSCP, + VCAP_IS1_HK_IP4_L3_IP4_DIP, + VCAP_IS1_HK_IP4_L3_IP4_SIP, + VCAP_IS1_HK_IP4_L3_PROTO, + VCAP_IS1_HK_IP4_TCP_UDP, + VCAP_IS1_HK_IP4_TCP, + VCAP_IS1_HK_IP4_L4_RNG, + VCAP_IS1_HK_IP4_IP_PAYLOAD_S1_5TUPLE, +}; + +enum vcap_is1_action_field { + VCAP_IS1_ACT_DSCP_ENA, + VCAP_IS1_ACT_DSCP_VAL, + VCAP_IS1_ACT_QOS_ENA, + VCAP_IS1_ACT_QOS_VAL, + VCAP_IS1_ACT_DP_ENA, + VCAP_IS1_ACT_DP_VAL, + VCAP_IS1_ACT_PAG_OVERRIDE_MASK, + VCAP_IS1_ACT_PAG_VAL, + VCAP_IS1_ACT_RSV, + VCAP_IS1_ACT_VID_REPLACE_ENA, + VCAP_IS1_ACT_VID_ADD_VAL, + VCAP_IS1_ACT_FID_SEL, + VCAP_IS1_ACT_FID_VAL, + VCAP_IS1_ACT_PCP_DEI_ENA, + VCAP_IS1_ACT_PCP_VAL, + VCAP_IS1_ACT_DEI_VAL, + VCAP_IS1_ACT_VLAN_POP_CNT_ENA, + VCAP_IS1_ACT_VLAN_POP_CNT, + VCAP_IS1_ACT_CUSTOM_ACE_TYPE_ENA, + VCAP_IS1_ACT_HIT_STICKY, +}; + #endif /* _OCELOT_VCAP_H_ */
VCAP IS1 is a VCAP module which can filter MAC, IP, VLAN, protocol, and TCP/UDP ports keys, and do Qos and VLAN retag actions. This patch added VCAP IS1 support in ocelot ace driver, which can supports vlan modify action of tc filter. Usage: tc qdisc add dev swp0 ingress tc filter add dev swp0 protocol 802.1Q parent ffff: flower \ skip_sw vlan_id 1 vlan_prio 1 action vlan modify id 2 priority 2 Signed-off-by: Xiaoliang Yang <xiaoliang.yang_1@nxp.com> --- drivers/net/dsa/ocelot/felix_vsc9959.c | 102 +++++++++++ drivers/net/ethernet/mscc/ocelot.c | 7 + drivers/net/ethernet/mscc/ocelot_ace.c | 198 +++++++++++++++++++++- drivers/net/ethernet/mscc/ocelot_ace.h | 9 + drivers/net/ethernet/mscc/ocelot_flower.c | 6 + drivers/net/ethernet/mscc/ocelot_regs.c | 1 + include/soc/mscc/ocelot.h | 1 + include/soc/mscc/ocelot_vcap.h | 93 +++++++++- 8 files changed, 415 insertions(+), 2 deletions(-)