hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
....@@ -7,6 +7,9 @@
77 #include <linux/errno.h>
88 #include <linux/rhashtable.h>
99 #include <linux/list.h>
10
+#include <linux/idr.h>
11
+#include <linux/refcount.h>
12
+#include <net/flow_offload.h>
1013
1114 #include "item.h"
1215 #include "trap.h"
....@@ -63,6 +66,10 @@
6366 void *ops_priv;
6467 struct rhashtable set_ht;
6568 struct rhashtable fwd_entry_ht;
69
+ struct rhashtable cookie_ht;
70
+ struct rhashtable policer_ht;
71
+ struct idr cookie_idr;
72
+ struct list_head policer_list;
6673 };
6774
6875 #define MLXSW_AFA_SET_LEN 0xA8
....@@ -83,9 +90,11 @@
8390 struct rhash_head ht_node;
8491 struct mlxsw_afa_set_ht_key ht_key;
8592 u32 kvdl_index;
86
- bool shared; /* Inserted in hashtable (doesn't mean that
93
+ u8 shared:1, /* Inserted in hashtable (doesn't mean that
8794 * kvdl_index is valid).
8895 */
96
+ has_trap:1,
97
+ has_police:1;
8998 unsigned int ref_count;
9099 struct mlxsw_afa_set *next; /* Pointer to the next set. */
91100 struct mlxsw_afa_set *prev; /* Pointer to the previous set,
....@@ -121,6 +130,70 @@
121130 .automatic_shrinking = true,
122131 };
123132
133
+struct mlxsw_afa_cookie {
134
+ struct rhash_head ht_node;
135
+ refcount_t ref_count;
136
+ struct rcu_head rcu;
137
+ u32 cookie_index;
138
+ struct flow_action_cookie fa_cookie;
139
+};
140
+
141
+static u32 mlxsw_afa_cookie_hash(const struct flow_action_cookie *fa_cookie,
142
+ u32 seed)
143
+{
144
+ return jhash2((u32 *) fa_cookie->cookie,
145
+ fa_cookie->cookie_len / sizeof(u32), seed);
146
+}
147
+
148
+static u32 mlxsw_afa_cookie_key_hashfn(const void *data, u32 len, u32 seed)
149
+{
150
+ const struct flow_action_cookie *fa_cookie = data;
151
+
152
+ return mlxsw_afa_cookie_hash(fa_cookie, seed);
153
+}
154
+
155
+static u32 mlxsw_afa_cookie_obj_hashfn(const void *data, u32 len, u32 seed)
156
+{
157
+ const struct mlxsw_afa_cookie *cookie = data;
158
+
159
+ return mlxsw_afa_cookie_hash(&cookie->fa_cookie, seed);
160
+}
161
+
162
+static int mlxsw_afa_cookie_obj_cmpfn(struct rhashtable_compare_arg *arg,
163
+ const void *obj)
164
+{
165
+ const struct flow_action_cookie *fa_cookie = arg->key;
166
+ const struct mlxsw_afa_cookie *cookie = obj;
167
+
168
+ if (cookie->fa_cookie.cookie_len == fa_cookie->cookie_len)
169
+ return memcmp(cookie->fa_cookie.cookie, fa_cookie->cookie,
170
+ fa_cookie->cookie_len);
171
+ return 1;
172
+}
173
+
174
+static const struct rhashtable_params mlxsw_afa_cookie_ht_params = {
175
+ .head_offset = offsetof(struct mlxsw_afa_cookie, ht_node),
176
+ .hashfn = mlxsw_afa_cookie_key_hashfn,
177
+ .obj_hashfn = mlxsw_afa_cookie_obj_hashfn,
178
+ .obj_cmpfn = mlxsw_afa_cookie_obj_cmpfn,
179
+ .automatic_shrinking = true,
180
+};
181
+
182
+struct mlxsw_afa_policer {
183
+ struct rhash_head ht_node;
184
+ struct list_head list; /* Member of policer_list */
185
+ refcount_t ref_count;
186
+ u32 fa_index;
187
+ u16 policer_index;
188
+};
189
+
190
+static const struct rhashtable_params mlxsw_afa_policer_ht_params = {
191
+ .key_len = sizeof(u32),
192
+ .key_offset = offsetof(struct mlxsw_afa_policer, fa_index),
193
+ .head_offset = offsetof(struct mlxsw_afa_policer, ht_node),
194
+ .automatic_shrinking = true,
195
+};
196
+
124197 struct mlxsw_afa *mlxsw_afa_create(unsigned int max_acts_per_set,
125198 const struct mlxsw_afa_ops *ops,
126199 void *ops_priv)
....@@ -138,11 +211,25 @@
138211 &mlxsw_afa_fwd_entry_ht_params);
139212 if (err)
140213 goto err_fwd_entry_rhashtable_init;
214
+ err = rhashtable_init(&mlxsw_afa->cookie_ht,
215
+ &mlxsw_afa_cookie_ht_params);
216
+ if (err)
217
+ goto err_cookie_rhashtable_init;
218
+ err = rhashtable_init(&mlxsw_afa->policer_ht,
219
+ &mlxsw_afa_policer_ht_params);
220
+ if (err)
221
+ goto err_policer_rhashtable_init;
222
+ idr_init(&mlxsw_afa->cookie_idr);
223
+ INIT_LIST_HEAD(&mlxsw_afa->policer_list);
141224 mlxsw_afa->max_acts_per_set = max_acts_per_set;
142225 mlxsw_afa->ops = ops;
143226 mlxsw_afa->ops_priv = ops_priv;
144227 return mlxsw_afa;
145228
229
+err_policer_rhashtable_init:
230
+ rhashtable_destroy(&mlxsw_afa->cookie_ht);
231
+err_cookie_rhashtable_init:
232
+ rhashtable_destroy(&mlxsw_afa->fwd_entry_ht);
146233 err_fwd_entry_rhashtable_init:
147234 rhashtable_destroy(&mlxsw_afa->set_ht);
148235 err_set_rhashtable_init:
....@@ -153,6 +240,11 @@
153240
154241 void mlxsw_afa_destroy(struct mlxsw_afa *mlxsw_afa)
155242 {
243
+ WARN_ON(!list_empty(&mlxsw_afa->policer_list));
244
+ WARN_ON(!idr_is_empty(&mlxsw_afa->cookie_idr));
245
+ idr_destroy(&mlxsw_afa->cookie_idr);
246
+ rhashtable_destroy(&mlxsw_afa->policer_ht);
247
+ rhashtable_destroy(&mlxsw_afa->cookie_ht);
156248 rhashtable_destroy(&mlxsw_afa->fwd_entry_ht);
157249 rhashtable_destroy(&mlxsw_afa->set_ht);
158250 kfree(mlxsw_afa);
....@@ -627,19 +719,317 @@
627719 return ERR_PTR(err);
628720 }
629721
722
+/* 20 bits is a maximum that hardware can handle in trap with userdef action
723
+ * and carry along with the trapped packet.
724
+ */
725
+#define MLXSW_AFA_COOKIE_INDEX_BITS 20
726
+#define MLXSW_AFA_COOKIE_INDEX_MAX ((1 << MLXSW_AFA_COOKIE_INDEX_BITS) - 1)
727
+
728
+static struct mlxsw_afa_cookie *
729
+mlxsw_afa_cookie_create(struct mlxsw_afa *mlxsw_afa,
730
+ const struct flow_action_cookie *fa_cookie)
731
+{
732
+ struct mlxsw_afa_cookie *cookie;
733
+ u32 cookie_index;
734
+ int err;
735
+
736
+ cookie = kzalloc(sizeof(*cookie) + fa_cookie->cookie_len, GFP_KERNEL);
737
+ if (!cookie)
738
+ return ERR_PTR(-ENOMEM);
739
+ refcount_set(&cookie->ref_count, 1);
740
+ memcpy(&cookie->fa_cookie, fa_cookie,
741
+ sizeof(*fa_cookie) + fa_cookie->cookie_len);
742
+
743
+ err = rhashtable_insert_fast(&mlxsw_afa->cookie_ht, &cookie->ht_node,
744
+ mlxsw_afa_cookie_ht_params);
745
+ if (err)
746
+ goto err_rhashtable_insert;
747
+
748
+ /* Start cookie indexes with 1. Leave the 0 index unused. Packets
749
+ * that come from the HW which are not dropped by drop-with-cookie
750
+ * action are going to pass cookie_index 0 to lookup.
751
+ */
752
+ cookie_index = 1;
753
+ err = idr_alloc_u32(&mlxsw_afa->cookie_idr, cookie, &cookie_index,
754
+ MLXSW_AFA_COOKIE_INDEX_MAX, GFP_KERNEL);
755
+ if (err)
756
+ goto err_idr_alloc;
757
+ cookie->cookie_index = cookie_index;
758
+ return cookie;
759
+
760
+err_idr_alloc:
761
+ rhashtable_remove_fast(&mlxsw_afa->cookie_ht, &cookie->ht_node,
762
+ mlxsw_afa_cookie_ht_params);
763
+err_rhashtable_insert:
764
+ kfree(cookie);
765
+ return ERR_PTR(err);
766
+}
767
+
768
+static void mlxsw_afa_cookie_destroy(struct mlxsw_afa *mlxsw_afa,
769
+ struct mlxsw_afa_cookie *cookie)
770
+{
771
+ idr_remove(&mlxsw_afa->cookie_idr, cookie->cookie_index);
772
+ rhashtable_remove_fast(&mlxsw_afa->cookie_ht, &cookie->ht_node,
773
+ mlxsw_afa_cookie_ht_params);
774
+ kfree_rcu(cookie, rcu);
775
+}
776
+
777
+static struct mlxsw_afa_cookie *
778
+mlxsw_afa_cookie_get(struct mlxsw_afa *mlxsw_afa,
779
+ const struct flow_action_cookie *fa_cookie)
780
+{
781
+ struct mlxsw_afa_cookie *cookie;
782
+
783
+ cookie = rhashtable_lookup_fast(&mlxsw_afa->cookie_ht, fa_cookie,
784
+ mlxsw_afa_cookie_ht_params);
785
+ if (cookie) {
786
+ refcount_inc(&cookie->ref_count);
787
+ return cookie;
788
+ }
789
+ return mlxsw_afa_cookie_create(mlxsw_afa, fa_cookie);
790
+}
791
+
792
+static void mlxsw_afa_cookie_put(struct mlxsw_afa *mlxsw_afa,
793
+ struct mlxsw_afa_cookie *cookie)
794
+{
795
+ if (!refcount_dec_and_test(&cookie->ref_count))
796
+ return;
797
+ mlxsw_afa_cookie_destroy(mlxsw_afa, cookie);
798
+}
799
+
800
+/* RCU read lock must be held */
801
+const struct flow_action_cookie *
802
+mlxsw_afa_cookie_lookup(struct mlxsw_afa *mlxsw_afa, u32 cookie_index)
803
+{
804
+ struct mlxsw_afa_cookie *cookie;
805
+
806
+ /* 0 index means no cookie */
807
+ if (!cookie_index)
808
+ return NULL;
809
+ cookie = idr_find(&mlxsw_afa->cookie_idr, cookie_index);
810
+ if (!cookie)
811
+ return NULL;
812
+ return &cookie->fa_cookie;
813
+}
814
+EXPORT_SYMBOL(mlxsw_afa_cookie_lookup);
815
+
816
+struct mlxsw_afa_cookie_ref {
817
+ struct mlxsw_afa_resource resource;
818
+ struct mlxsw_afa_cookie *cookie;
819
+};
820
+
821
+static void
822
+mlxsw_afa_cookie_ref_destroy(struct mlxsw_afa_block *block,
823
+ struct mlxsw_afa_cookie_ref *cookie_ref)
824
+{
825
+ mlxsw_afa_resource_del(&cookie_ref->resource);
826
+ mlxsw_afa_cookie_put(block->afa, cookie_ref->cookie);
827
+ kfree(cookie_ref);
828
+}
829
+
830
+static void
831
+mlxsw_afa_cookie_ref_destructor(struct mlxsw_afa_block *block,
832
+ struct mlxsw_afa_resource *resource)
833
+{
834
+ struct mlxsw_afa_cookie_ref *cookie_ref;
835
+
836
+ cookie_ref = container_of(resource, struct mlxsw_afa_cookie_ref,
837
+ resource);
838
+ mlxsw_afa_cookie_ref_destroy(block, cookie_ref);
839
+}
840
+
841
+static struct mlxsw_afa_cookie_ref *
842
+mlxsw_afa_cookie_ref_create(struct mlxsw_afa_block *block,
843
+ const struct flow_action_cookie *fa_cookie)
844
+{
845
+ struct mlxsw_afa_cookie_ref *cookie_ref;
846
+ struct mlxsw_afa_cookie *cookie;
847
+ int err;
848
+
849
+ cookie_ref = kzalloc(sizeof(*cookie_ref), GFP_KERNEL);
850
+ if (!cookie_ref)
851
+ return ERR_PTR(-ENOMEM);
852
+ cookie = mlxsw_afa_cookie_get(block->afa, fa_cookie);
853
+ if (IS_ERR(cookie)) {
854
+ err = PTR_ERR(cookie);
855
+ goto err_cookie_get;
856
+ }
857
+ cookie_ref->cookie = cookie;
858
+ cookie_ref->resource.destructor = mlxsw_afa_cookie_ref_destructor;
859
+ mlxsw_afa_resource_add(block, &cookie_ref->resource);
860
+ return cookie_ref;
861
+
862
+err_cookie_get:
863
+ kfree(cookie_ref);
864
+ return ERR_PTR(err);
865
+}
866
+
867
+static struct mlxsw_afa_policer *
868
+mlxsw_afa_policer_create(struct mlxsw_afa *mlxsw_afa, u32 fa_index,
869
+ u64 rate_bytes_ps, u32 burst,
870
+ struct netlink_ext_ack *extack)
871
+{
872
+ struct mlxsw_afa_policer *policer;
873
+ int err;
874
+
875
+ policer = kzalloc(sizeof(*policer), GFP_KERNEL);
876
+ if (!policer)
877
+ return ERR_PTR(-ENOMEM);
878
+
879
+ err = mlxsw_afa->ops->policer_add(mlxsw_afa->ops_priv, rate_bytes_ps,
880
+ burst, &policer->policer_index,
881
+ extack);
882
+ if (err)
883
+ goto err_policer_add;
884
+
885
+ refcount_set(&policer->ref_count, 1);
886
+ policer->fa_index = fa_index;
887
+
888
+ err = rhashtable_insert_fast(&mlxsw_afa->policer_ht, &policer->ht_node,
889
+ mlxsw_afa_policer_ht_params);
890
+ if (err)
891
+ goto err_rhashtable_insert;
892
+
893
+ list_add_tail(&policer->list, &mlxsw_afa->policer_list);
894
+
895
+ return policer;
896
+
897
+err_rhashtable_insert:
898
+ mlxsw_afa->ops->policer_del(mlxsw_afa->ops_priv,
899
+ policer->policer_index);
900
+err_policer_add:
901
+ kfree(policer);
902
+ return ERR_PTR(err);
903
+}
904
+
905
+static void mlxsw_afa_policer_destroy(struct mlxsw_afa *mlxsw_afa,
906
+ struct mlxsw_afa_policer *policer)
907
+{
908
+ list_del(&policer->list);
909
+ rhashtable_remove_fast(&mlxsw_afa->policer_ht, &policer->ht_node,
910
+ mlxsw_afa_policer_ht_params);
911
+ mlxsw_afa->ops->policer_del(mlxsw_afa->ops_priv,
912
+ policer->policer_index);
913
+ kfree(policer);
914
+}
915
+
916
+static struct mlxsw_afa_policer *
917
+mlxsw_afa_policer_get(struct mlxsw_afa *mlxsw_afa, u32 fa_index,
918
+ u64 rate_bytes_ps, u32 burst,
919
+ struct netlink_ext_ack *extack)
920
+{
921
+ struct mlxsw_afa_policer *policer;
922
+
923
+ policer = rhashtable_lookup_fast(&mlxsw_afa->policer_ht, &fa_index,
924
+ mlxsw_afa_policer_ht_params);
925
+ if (policer) {
926
+ refcount_inc(&policer->ref_count);
927
+ return policer;
928
+ }
929
+
930
+ return mlxsw_afa_policer_create(mlxsw_afa, fa_index, rate_bytes_ps,
931
+ burst, extack);
932
+}
933
+
934
+static void mlxsw_afa_policer_put(struct mlxsw_afa *mlxsw_afa,
935
+ struct mlxsw_afa_policer *policer)
936
+{
937
+ if (!refcount_dec_and_test(&policer->ref_count))
938
+ return;
939
+ mlxsw_afa_policer_destroy(mlxsw_afa, policer);
940
+}
941
+
942
+struct mlxsw_afa_policer_ref {
943
+ struct mlxsw_afa_resource resource;
944
+ struct mlxsw_afa_policer *policer;
945
+};
946
+
947
+static void
948
+mlxsw_afa_policer_ref_destroy(struct mlxsw_afa_block *block,
949
+ struct mlxsw_afa_policer_ref *policer_ref)
950
+{
951
+ mlxsw_afa_resource_del(&policer_ref->resource);
952
+ mlxsw_afa_policer_put(block->afa, policer_ref->policer);
953
+ kfree(policer_ref);
954
+}
955
+
956
+static void
957
+mlxsw_afa_policer_ref_destructor(struct mlxsw_afa_block *block,
958
+ struct mlxsw_afa_resource *resource)
959
+{
960
+ struct mlxsw_afa_policer_ref *policer_ref;
961
+
962
+ policer_ref = container_of(resource, struct mlxsw_afa_policer_ref,
963
+ resource);
964
+ mlxsw_afa_policer_ref_destroy(block, policer_ref);
965
+}
966
+
967
+static struct mlxsw_afa_policer_ref *
968
+mlxsw_afa_policer_ref_create(struct mlxsw_afa_block *block, u32 fa_index,
969
+ u64 rate_bytes_ps, u32 burst,
970
+ struct netlink_ext_ack *extack)
971
+{
972
+ struct mlxsw_afa_policer_ref *policer_ref;
973
+ struct mlxsw_afa_policer *policer;
974
+ int err;
975
+
976
+ policer_ref = kzalloc(sizeof(*policer_ref), GFP_KERNEL);
977
+ if (!policer_ref)
978
+ return ERR_PTR(-ENOMEM);
979
+
980
+ policer = mlxsw_afa_policer_get(block->afa, fa_index, rate_bytes_ps,
981
+ burst, extack);
982
+ if (IS_ERR(policer)) {
983
+ err = PTR_ERR(policer);
984
+ goto err_policer_get;
985
+ }
986
+
987
+ policer_ref->policer = policer;
988
+ policer_ref->resource.destructor = mlxsw_afa_policer_ref_destructor;
989
+ mlxsw_afa_resource_add(block, &policer_ref->resource);
990
+
991
+ return policer_ref;
992
+
993
+err_policer_get:
994
+ kfree(policer_ref);
995
+ return ERR_PTR(err);
996
+}
997
+
630998 #define MLXSW_AFA_ONE_ACTION_LEN 32
631999 #define MLXSW_AFA_PAYLOAD_OFFSET 4
6321000
633
-static char *mlxsw_afa_block_append_action(struct mlxsw_afa_block *block,
634
- u8 action_code, u8 action_size)
1001
+enum mlxsw_afa_action_type {
1002
+ MLXSW_AFA_ACTION_TYPE_TRAP,
1003
+ MLXSW_AFA_ACTION_TYPE_POLICE,
1004
+ MLXSW_AFA_ACTION_TYPE_OTHER,
1005
+};
1006
+
1007
+static bool
1008
+mlxsw_afa_block_need_split(const struct mlxsw_afa_block *block,
1009
+ enum mlxsw_afa_action_type type)
1010
+{
1011
+ struct mlxsw_afa_set *cur_set = block->cur_set;
1012
+
1013
+ /* Due to a hardware limitation, police action cannot be in the same
1014
+ * action set with MLXSW_AFA_TRAP_CODE or MLXSW_AFA_TRAPWU_CODE
1015
+ * actions. Work around this limitation by creating a new action set
1016
+ * and place the new action there.
1017
+ */
1018
+ return (cur_set->has_trap && type == MLXSW_AFA_ACTION_TYPE_POLICE) ||
1019
+ (cur_set->has_police && type == MLXSW_AFA_ACTION_TYPE_TRAP);
1020
+}
1021
+
1022
+static char *mlxsw_afa_block_append_action_ext(struct mlxsw_afa_block *block,
1023
+ u8 action_code, u8 action_size,
1024
+ enum mlxsw_afa_action_type type)
6351025 {
6361026 char *oneact;
6371027 char *actions;
6381028
6391029 if (block->finished)
6401030 return ERR_PTR(-EINVAL);
641
- if (block->cur_act_index + action_size >
642
- block->afa->max_acts_per_set) {
1031
+ if (block->cur_act_index + action_size > block->afa->max_acts_per_set ||
1032
+ mlxsw_afa_block_need_split(block, type)) {
6431033 struct mlxsw_afa_set *set;
6441034
6451035 /* The appended action won't fit into the current action set,
....@@ -654,11 +1044,30 @@
6541044 block->cur_set = set;
6551045 }
6561046
1047
+ switch (type) {
1048
+ case MLXSW_AFA_ACTION_TYPE_TRAP:
1049
+ block->cur_set->has_trap = true;
1050
+ break;
1051
+ case MLXSW_AFA_ACTION_TYPE_POLICE:
1052
+ block->cur_set->has_police = true;
1053
+ break;
1054
+ default:
1055
+ break;
1056
+ }
1057
+
6571058 actions = block->cur_set->ht_key.enc_actions;
6581059 oneact = actions + block->cur_act_index * MLXSW_AFA_ONE_ACTION_LEN;
6591060 block->cur_act_index += action_size;
6601061 mlxsw_afa_all_action_type_set(oneact, action_code);
6611062 return oneact + MLXSW_AFA_PAYLOAD_OFFSET;
1063
+}
1064
+
1065
+static char *mlxsw_afa_block_append_action(struct mlxsw_afa_block *block,
1066
+ u8 action_code, u8 action_size)
1067
+{
1068
+ return mlxsw_afa_block_append_action_ext(block, action_code,
1069
+ action_size,
1070
+ MLXSW_AFA_ACTION_TYPE_OTHER);
6621071 }
6631072
6641073 /* VLAN Action
....@@ -747,97 +1156,180 @@
7471156 }
7481157 EXPORT_SYMBOL(mlxsw_afa_block_append_vlan_modify);
7491158
750
-/* Trap / Discard Action
751
- * ---------------------
752
- * The Trap / Discard action enables trapping / mirroring packets to the CPU
1159
+/* Trap Action / Trap With Userdef Action
1160
+ * --------------------------------------
1161
+ * The Trap action enables trapping / mirroring packets to the CPU
7531162 * as well as discarding packets.
7541163 * The ACL Trap / Discard separates the forward/discard control from CPU
7551164 * trap control. In addition, the Trap / Discard action enables activating
7561165 * SPAN (port mirroring).
1166
+ *
1167
+ * The Trap with userdef action action has the same functionality as
1168
+ * the Trap action with addition of user defined value that can be set
1169
+ * and used by higher layer applications.
7571170 */
7581171
759
-#define MLXSW_AFA_TRAPDISC_CODE 0x03
760
-#define MLXSW_AFA_TRAPDISC_SIZE 1
1172
+#define MLXSW_AFA_TRAP_CODE 0x03
1173
+#define MLXSW_AFA_TRAP_SIZE 1
7611174
762
-enum mlxsw_afa_trapdisc_trap_action {
763
- MLXSW_AFA_TRAPDISC_TRAP_ACTION_NOP = 0,
764
- MLXSW_AFA_TRAPDISC_TRAP_ACTION_TRAP = 2,
1175
+#define MLXSW_AFA_TRAPWU_CODE 0x04
1176
+#define MLXSW_AFA_TRAPWU_SIZE 2
1177
+
1178
+enum mlxsw_afa_trap_trap_action {
1179
+ MLXSW_AFA_TRAP_TRAP_ACTION_NOP = 0,
1180
+ MLXSW_AFA_TRAP_TRAP_ACTION_TRAP = 2,
7651181 };
7661182
767
-/* afa_trapdisc_trap_action
1183
+/* afa_trap_trap_action
7681184 * Trap Action.
7691185 */
770
-MLXSW_ITEM32(afa, trapdisc, trap_action, 0x00, 24, 4);
1186
+MLXSW_ITEM32(afa, trap, trap_action, 0x00, 24, 4);
7711187
772
-enum mlxsw_afa_trapdisc_forward_action {
773
- MLXSW_AFA_TRAPDISC_FORWARD_ACTION_FORWARD = 1,
774
- MLXSW_AFA_TRAPDISC_FORWARD_ACTION_DISCARD = 3,
1188
+enum mlxsw_afa_trap_forward_action {
1189
+ MLXSW_AFA_TRAP_FORWARD_ACTION_FORWARD = 1,
1190
+ MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD = 3,
7751191 };
7761192
777
-/* afa_trapdisc_forward_action
1193
+/* afa_trap_forward_action
7781194 * Forward Action.
7791195 */
780
-MLXSW_ITEM32(afa, trapdisc, forward_action, 0x00, 0, 4);
1196
+MLXSW_ITEM32(afa, trap, forward_action, 0x00, 0, 4);
7811197
782
-/* afa_trapdisc_trap_id
1198
+/* afa_trap_trap_id
7831199 * Trap ID to configure.
7841200 */
785
-MLXSW_ITEM32(afa, trapdisc, trap_id, 0x04, 0, 9);
1201
+MLXSW_ITEM32(afa, trap, trap_id, 0x04, 0, 9);
7861202
787
-/* afa_trapdisc_mirror_agent
1203
+/* afa_trap_mirror_agent
7881204 * Mirror agent.
7891205 */
790
-MLXSW_ITEM32(afa, trapdisc, mirror_agent, 0x08, 29, 3);
1206
+MLXSW_ITEM32(afa, trap, mirror_agent, 0x08, 29, 3);
7911207
792
-/* afa_trapdisc_mirror_enable
1208
+/* afa_trap_mirror_enable
7931209 * Mirror enable.
7941210 */
795
-MLXSW_ITEM32(afa, trapdisc, mirror_enable, 0x08, 24, 1);
1211
+MLXSW_ITEM32(afa, trap, mirror_enable, 0x08, 24, 1);
1212
+
1213
+/* user_def_val
1214
+ * Value for the SW usage. Can be used to pass information of which
1215
+ * rule has caused a trap. This may be overwritten by later traps.
1216
+ * This field does a set on the packet's user_def_val only if this
1217
+ * is the first trap_id or if the trap_id has replaced the previous
1218
+ * packet's trap_id.
1219
+ */
1220
+MLXSW_ITEM32(afa, trap, user_def_val, 0x0C, 0, 20);
7961221
7971222 static inline void
798
-mlxsw_afa_trapdisc_pack(char *payload,
799
- enum mlxsw_afa_trapdisc_trap_action trap_action,
800
- enum mlxsw_afa_trapdisc_forward_action forward_action,
801
- u16 trap_id)
1223
+mlxsw_afa_trap_pack(char *payload,
1224
+ enum mlxsw_afa_trap_trap_action trap_action,
1225
+ enum mlxsw_afa_trap_forward_action forward_action,
1226
+ u16 trap_id)
8021227 {
803
- mlxsw_afa_trapdisc_trap_action_set(payload, trap_action);
804
- mlxsw_afa_trapdisc_forward_action_set(payload, forward_action);
805
- mlxsw_afa_trapdisc_trap_id_set(payload, trap_id);
1228
+ mlxsw_afa_trap_trap_action_set(payload, trap_action);
1229
+ mlxsw_afa_trap_forward_action_set(payload, forward_action);
1230
+ mlxsw_afa_trap_trap_id_set(payload, trap_id);
8061231 }
8071232
8081233 static inline void
809
-mlxsw_afa_trapdisc_mirror_pack(char *payload, bool mirror_enable,
810
- u8 mirror_agent)
1234
+mlxsw_afa_trapwu_pack(char *payload,
1235
+ enum mlxsw_afa_trap_trap_action trap_action,
1236
+ enum mlxsw_afa_trap_forward_action forward_action,
1237
+ u16 trap_id, u32 user_def_val)
8111238 {
812
- mlxsw_afa_trapdisc_mirror_enable_set(payload, mirror_enable);
813
- mlxsw_afa_trapdisc_mirror_agent_set(payload, mirror_agent);
1239
+ mlxsw_afa_trap_pack(payload, trap_action, forward_action, trap_id);
1240
+ mlxsw_afa_trap_user_def_val_set(payload, user_def_val);
8141241 }
8151242
816
-int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block)
1243
+static inline void
1244
+mlxsw_afa_trap_mirror_pack(char *payload, bool mirror_enable,
1245
+ u8 mirror_agent)
8171246 {
818
- char *act = mlxsw_afa_block_append_action(block,
819
- MLXSW_AFA_TRAPDISC_CODE,
820
- MLXSW_AFA_TRAPDISC_SIZE);
1247
+ mlxsw_afa_trap_mirror_enable_set(payload, mirror_enable);
1248
+ mlxsw_afa_trap_mirror_agent_set(payload, mirror_agent);
1249
+}
1250
+
1251
+static char *mlxsw_afa_block_append_action_trap(struct mlxsw_afa_block *block,
1252
+ u8 action_code, u8 action_size)
1253
+{
1254
+ return mlxsw_afa_block_append_action_ext(block, action_code,
1255
+ action_size,
1256
+ MLXSW_AFA_ACTION_TYPE_TRAP);
1257
+}
1258
+
1259
+static int mlxsw_afa_block_append_drop_plain(struct mlxsw_afa_block *block,
1260
+ bool ingress)
1261
+{
1262
+ char *act = mlxsw_afa_block_append_action_trap(block,
1263
+ MLXSW_AFA_TRAP_CODE,
1264
+ MLXSW_AFA_TRAP_SIZE);
8211265
8221266 if (IS_ERR(act))
8231267 return PTR_ERR(act);
824
- mlxsw_afa_trapdisc_pack(act, MLXSW_AFA_TRAPDISC_TRAP_ACTION_NOP,
825
- MLXSW_AFA_TRAPDISC_FORWARD_ACTION_DISCARD, 0);
1268
+ mlxsw_afa_trap_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_TRAP,
1269
+ MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD,
1270
+ ingress ? MLXSW_TRAP_ID_DISCARD_INGRESS_ACL :
1271
+ MLXSW_TRAP_ID_DISCARD_EGRESS_ACL);
8261272 return 0;
1273
+}
1274
+
1275
+static int
1276
+mlxsw_afa_block_append_drop_with_cookie(struct mlxsw_afa_block *block,
1277
+ bool ingress,
1278
+ const struct flow_action_cookie *fa_cookie,
1279
+ struct netlink_ext_ack *extack)
1280
+{
1281
+ struct mlxsw_afa_cookie_ref *cookie_ref;
1282
+ u32 cookie_index;
1283
+ char *act;
1284
+ int err;
1285
+
1286
+ cookie_ref = mlxsw_afa_cookie_ref_create(block, fa_cookie);
1287
+ if (IS_ERR(cookie_ref)) {
1288
+ NL_SET_ERR_MSG_MOD(extack, "Cannot create cookie for drop action");
1289
+ return PTR_ERR(cookie_ref);
1290
+ }
1291
+ cookie_index = cookie_ref->cookie->cookie_index;
1292
+
1293
+ act = mlxsw_afa_block_append_action_trap(block, MLXSW_AFA_TRAPWU_CODE,
1294
+ MLXSW_AFA_TRAPWU_SIZE);
1295
+ if (IS_ERR(act)) {
1296
+ NL_SET_ERR_MSG_MOD(extack, "Cannot append drop with cookie action");
1297
+ err = PTR_ERR(act);
1298
+ goto err_append_action;
1299
+ }
1300
+ mlxsw_afa_trapwu_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_TRAP,
1301
+ MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD,
1302
+ ingress ? MLXSW_TRAP_ID_DISCARD_INGRESS_ACL :
1303
+ MLXSW_TRAP_ID_DISCARD_EGRESS_ACL,
1304
+ cookie_index);
1305
+ return 0;
1306
+
1307
+err_append_action:
1308
+ mlxsw_afa_cookie_ref_destroy(block, cookie_ref);
1309
+ return err;
1310
+}
1311
+
1312
+int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress,
1313
+ const struct flow_action_cookie *fa_cookie,
1314
+ struct netlink_ext_ack *extack)
1315
+{
1316
+ return fa_cookie ?
1317
+ mlxsw_afa_block_append_drop_with_cookie(block, ingress,
1318
+ fa_cookie, extack) :
1319
+ mlxsw_afa_block_append_drop_plain(block, ingress);
8271320 }
8281321 EXPORT_SYMBOL(mlxsw_afa_block_append_drop);
8291322
8301323 int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id)
8311324 {
832
- char *act = mlxsw_afa_block_append_action(block,
833
- MLXSW_AFA_TRAPDISC_CODE,
834
- MLXSW_AFA_TRAPDISC_SIZE);
1325
+ char *act = mlxsw_afa_block_append_action_trap(block,
1326
+ MLXSW_AFA_TRAP_CODE,
1327
+ MLXSW_AFA_TRAP_SIZE);
8351328
8361329 if (IS_ERR(act))
8371330 return PTR_ERR(act);
838
- mlxsw_afa_trapdisc_pack(act, MLXSW_AFA_TRAPDISC_TRAP_ACTION_TRAP,
839
- MLXSW_AFA_TRAPDISC_FORWARD_ACTION_DISCARD,
840
- trap_id);
1331
+ mlxsw_afa_trap_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_TRAP,
1332
+ MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD, trap_id);
8411333 return 0;
8421334 }
8431335 EXPORT_SYMBOL(mlxsw_afa_block_append_trap);
....@@ -845,15 +1337,14 @@
8451337 int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
8461338 u16 trap_id)
8471339 {
848
- char *act = mlxsw_afa_block_append_action(block,
849
- MLXSW_AFA_TRAPDISC_CODE,
850
- MLXSW_AFA_TRAPDISC_SIZE);
1340
+ char *act = mlxsw_afa_block_append_action_trap(block,
1341
+ MLXSW_AFA_TRAP_CODE,
1342
+ MLXSW_AFA_TRAP_SIZE);
8511343
8521344 if (IS_ERR(act))
8531345 return PTR_ERR(act);
854
- mlxsw_afa_trapdisc_pack(act, MLXSW_AFA_TRAPDISC_TRAP_ACTION_TRAP,
855
- MLXSW_AFA_TRAPDISC_FORWARD_ACTION_FORWARD,
856
- trap_id);
1346
+ mlxsw_afa_trap_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_TRAP,
1347
+ MLXSW_AFA_TRAP_FORWARD_ACTION_FORWARD, trap_id);
8571348 return 0;
8581349 }
8591350 EXPORT_SYMBOL(mlxsw_afa_block_append_trap_and_forward);
....@@ -919,14 +1410,15 @@
9191410 mlxsw_afa_block_append_allocated_mirror(struct mlxsw_afa_block *block,
9201411 u8 mirror_agent)
9211412 {
922
- char *act = mlxsw_afa_block_append_action(block,
923
- MLXSW_AFA_TRAPDISC_CODE,
924
- MLXSW_AFA_TRAPDISC_SIZE);
1413
+ char *act = mlxsw_afa_block_append_action_trap(block,
1414
+ MLXSW_AFA_TRAP_CODE,
1415
+ MLXSW_AFA_TRAP_SIZE);
1416
+
9251417 if (IS_ERR(act))
9261418 return PTR_ERR(act);
927
- mlxsw_afa_trapdisc_pack(act, MLXSW_AFA_TRAPDISC_TRAP_ACTION_NOP,
928
- MLXSW_AFA_TRAPDISC_FORWARD_ACTION_FORWARD, 0);
929
- mlxsw_afa_trapdisc_mirror_pack(act, true, mirror_agent);
1419
+ mlxsw_afa_trap_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_NOP,
1420
+ MLXSW_AFA_TRAP_FORWARD_ACTION_FORWARD, 0);
1421
+ mlxsw_afa_trap_mirror_pack(act, true, mirror_agent);
9301422 return 0;
9311423 }
9321424
....@@ -957,6 +1449,179 @@
9571449 return err;
9581450 }
9591451 EXPORT_SYMBOL(mlxsw_afa_block_append_mirror);
1452
+
1453
+/* QoS Action
1454
+ * ----------
1455
+ * The QOS_ACTION is used for manipulating the QoS attributes of a packet. It
1456
+ * can be used to change the DCSP, ECN, Color and Switch Priority of the packet.
1457
+ * Note that PCP field can be changed using the VLAN action.
1458
+ */
1459
+
1460
+#define MLXSW_AFA_QOS_CODE 0x06
1461
+#define MLXSW_AFA_QOS_SIZE 1
1462
+
1463
+enum mlxsw_afa_qos_ecn_cmd {
1464
+ /* Do nothing */
1465
+ MLXSW_AFA_QOS_ECN_CMD_NOP,
1466
+ /* Set ECN to afa_qos_ecn */
1467
+ MLXSW_AFA_QOS_ECN_CMD_SET,
1468
+};
1469
+
1470
+/* afa_qos_ecn_cmd
1471
+ */
1472
+MLXSW_ITEM32(afa, qos, ecn_cmd, 0x04, 29, 3);
1473
+
1474
+/* afa_qos_ecn
1475
+ * ECN value.
1476
+ */
1477
+MLXSW_ITEM32(afa, qos, ecn, 0x04, 24, 2);
1478
+
1479
+enum mlxsw_afa_qos_dscp_cmd {
1480
+ /* Do nothing */
1481
+ MLXSW_AFA_QOS_DSCP_CMD_NOP,
1482
+ /* Set DSCP 3 LSB bits according to dscp[2:0] */
1483
+ MLXSW_AFA_QOS_DSCP_CMD_SET_3LSB,
1484
+ /* Set DSCP 3 MSB bits according to dscp[5:3] */
1485
+ MLXSW_AFA_QOS_DSCP_CMD_SET_3MSB,
1486
+ /* Set DSCP 6 bits according to dscp[5:0] */
1487
+ MLXSW_AFA_QOS_DSCP_CMD_SET_ALL,
1488
+};
1489
+
1490
+/* afa_qos_dscp_cmd
1491
+ * DSCP command.
1492
+ */
1493
+MLXSW_ITEM32(afa, qos, dscp_cmd, 0x04, 14, 2);
1494
+
1495
+/* afa_qos_dscp
1496
+ * DSCP value.
1497
+ */
1498
+MLXSW_ITEM32(afa, qos, dscp, 0x04, 0, 6);
1499
+
1500
+enum mlxsw_afa_qos_switch_prio_cmd {
1501
+ /* Do nothing */
1502
+ MLXSW_AFA_QOS_SWITCH_PRIO_CMD_NOP,
1503
+ /* Set Switch Priority to afa_qos_switch_prio */
1504
+ MLXSW_AFA_QOS_SWITCH_PRIO_CMD_SET,
1505
+};
1506
+
1507
+/* afa_qos_switch_prio_cmd
1508
+ */
1509
+MLXSW_ITEM32(afa, qos, switch_prio_cmd, 0x08, 14, 2);
1510
+
1511
+/* afa_qos_switch_prio
1512
+ * Switch Priority.
1513
+ */
1514
+MLXSW_ITEM32(afa, qos, switch_prio, 0x08, 0, 4);
1515
+
1516
+enum mlxsw_afa_qos_dscp_rw {
1517
+ MLXSW_AFA_QOS_DSCP_RW_PRESERVE,
1518
+ MLXSW_AFA_QOS_DSCP_RW_SET,
1519
+ MLXSW_AFA_QOS_DSCP_RW_CLEAR,
1520
+};
1521
+
1522
+/* afa_qos_dscp_rw
1523
+ * DSCP Re-write Enable. Controlling the rewrite_enable for DSCP.
1524
+ */
1525
+MLXSW_ITEM32(afa, qos, dscp_rw, 0x0C, 30, 2);
1526
+
1527
+static inline void
1528
+mlxsw_afa_qos_ecn_pack(char *payload,
1529
+ enum mlxsw_afa_qos_ecn_cmd ecn_cmd, u8 ecn)
1530
+{
1531
+ mlxsw_afa_qos_ecn_cmd_set(payload, ecn_cmd);
1532
+ mlxsw_afa_qos_ecn_set(payload, ecn);
1533
+}
1534
+
1535
+static inline void
1536
+mlxsw_afa_qos_dscp_pack(char *payload,
1537
+ enum mlxsw_afa_qos_dscp_cmd dscp_cmd, u8 dscp)
1538
+{
1539
+ mlxsw_afa_qos_dscp_cmd_set(payload, dscp_cmd);
1540
+ mlxsw_afa_qos_dscp_set(payload, dscp);
1541
+}
1542
+
1543
+static inline void
1544
+mlxsw_afa_qos_switch_prio_pack(char *payload,
1545
+ enum mlxsw_afa_qos_switch_prio_cmd prio_cmd,
1546
+ u8 prio)
1547
+{
1548
+ mlxsw_afa_qos_switch_prio_cmd_set(payload, prio_cmd);
1549
+ mlxsw_afa_qos_switch_prio_set(payload, prio);
1550
+}
1551
+
1552
+static int __mlxsw_afa_block_append_qos_dsfield(struct mlxsw_afa_block *block,
1553
+ bool set_dscp, u8 dscp,
1554
+ bool set_ecn, u8 ecn,
1555
+ struct netlink_ext_ack *extack)
1556
+{
1557
+ char *act = mlxsw_afa_block_append_action(block,
1558
+ MLXSW_AFA_QOS_CODE,
1559
+ MLXSW_AFA_QOS_SIZE);
1560
+
1561
+ if (IS_ERR(act)) {
1562
+ NL_SET_ERR_MSG_MOD(extack, "Cannot append QOS action");
1563
+ return PTR_ERR(act);
1564
+ }
1565
+
1566
+ if (set_ecn)
1567
+ mlxsw_afa_qos_ecn_pack(act, MLXSW_AFA_QOS_ECN_CMD_SET, ecn);
1568
+ if (set_dscp) {
1569
+ mlxsw_afa_qos_dscp_pack(act, MLXSW_AFA_QOS_DSCP_CMD_SET_ALL,
1570
+ dscp);
1571
+ mlxsw_afa_qos_dscp_rw_set(act, MLXSW_AFA_QOS_DSCP_RW_CLEAR);
1572
+ }
1573
+
1574
+ return 0;
1575
+}
1576
+
1577
+int mlxsw_afa_block_append_qos_dsfield(struct mlxsw_afa_block *block,
1578
+ u8 dsfield,
1579
+ struct netlink_ext_ack *extack)
1580
+{
1581
+ return __mlxsw_afa_block_append_qos_dsfield(block,
1582
+ true, dsfield >> 2,
1583
+ true, dsfield & 0x03,
1584
+ extack);
1585
+}
1586
+EXPORT_SYMBOL(mlxsw_afa_block_append_qos_dsfield);
1587
+
1588
+int mlxsw_afa_block_append_qos_dscp(struct mlxsw_afa_block *block,
1589
+ u8 dscp, struct netlink_ext_ack *extack)
1590
+{
1591
+ return __mlxsw_afa_block_append_qos_dsfield(block,
1592
+ true, dscp,
1593
+ false, 0,
1594
+ extack);
1595
+}
1596
+EXPORT_SYMBOL(mlxsw_afa_block_append_qos_dscp);
1597
+
1598
+int mlxsw_afa_block_append_qos_ecn(struct mlxsw_afa_block *block,
1599
+ u8 ecn, struct netlink_ext_ack *extack)
1600
+{
1601
+ return __mlxsw_afa_block_append_qos_dsfield(block,
1602
+ false, 0,
1603
+ true, ecn,
1604
+ extack);
1605
+}
1606
+EXPORT_SYMBOL(mlxsw_afa_block_append_qos_ecn);
1607
+
1608
+int mlxsw_afa_block_append_qos_switch_prio(struct mlxsw_afa_block *block,
1609
+ u8 prio,
1610
+ struct netlink_ext_ack *extack)
1611
+{
1612
+ char *act = mlxsw_afa_block_append_action(block,
1613
+ MLXSW_AFA_QOS_CODE,
1614
+ MLXSW_AFA_QOS_SIZE);
1615
+
1616
+ if (IS_ERR(act)) {
1617
+ NL_SET_ERR_MSG_MOD(extack, "Cannot append QOS action");
1618
+ return PTR_ERR(act);
1619
+ }
1620
+ mlxsw_afa_qos_switch_prio_pack(act, MLXSW_AFA_QOS_SWITCH_PRIO_CMD_SET,
1621
+ prio);
1622
+ return 0;
1623
+}
1624
+EXPORT_SYMBOL(mlxsw_afa_block_append_qos_switch_prio);
9601625
9611626 /* Forwarding Action
9621627 * -----------------
....@@ -1043,6 +1708,19 @@
10431708 #define MLXSW_AFA_POLCNT_CODE 0x08
10441709 #define MLXSW_AFA_POLCNT_SIZE 1
10451710
1711
+enum {
1712
+ MLXSW_AFA_POLCNT_COUNTER,
1713
+ MLXSW_AFA_POLCNT_POLICER,
1714
+};
1715
+
1716
+/* afa_polcnt_c_p
1717
+ * Counter or policer.
1718
+ * Indicates whether the action binds a policer or a counter to the flow.
1719
+ * 0: Counter
1720
+ * 1: Policer
1721
+ */
1722
+MLXSW_ITEM32(afa, polcnt, c_p, 0x00, 31, 1);
1723
+
10461724 enum mlxsw_afa_polcnt_counter_set_type {
10471725 /* No count */
10481726 MLXSW_AFA_POLCNT_COUNTER_SET_TYPE_NO_COUNT = 0x00,
....@@ -1062,13 +1740,26 @@
10621740 */
10631741 MLXSW_ITEM32(afa, polcnt, counter_index, 0x04, 0, 24);
10641742
1743
+/* afa_polcnt_pid
1744
+ * Policer ID.
1745
+ * Reserved when c_p = 0
1746
+ */
1747
+MLXSW_ITEM32(afa, polcnt, pid, 0x08, 0, 14);
1748
+
10651749 static inline void
10661750 mlxsw_afa_polcnt_pack(char *payload,
10671751 enum mlxsw_afa_polcnt_counter_set_type set_type,
10681752 u32 counter_index)
10691753 {
1754
+ mlxsw_afa_polcnt_c_p_set(payload, MLXSW_AFA_POLCNT_COUNTER);
10701755 mlxsw_afa_polcnt_counter_set_type_set(payload, set_type);
10711756 mlxsw_afa_polcnt_counter_index_set(payload, counter_index);
1757
+}
1758
+
1759
+static void mlxsw_afa_polcnt_policer_pack(char *payload, u16 policer_index)
1760
+{
1761
+ mlxsw_afa_polcnt_c_p_set(payload, MLXSW_AFA_POLCNT_POLICER);
1762
+ mlxsw_afa_polcnt_pid_set(payload, policer_index);
10721763 }
10731764
10741765 int mlxsw_afa_block_append_allocated_counter(struct mlxsw_afa_block *block,
....@@ -1113,6 +1804,40 @@
11131804 return err;
11141805 }
11151806 EXPORT_SYMBOL(mlxsw_afa_block_append_counter);
1807
+
1808
+int mlxsw_afa_block_append_police(struct mlxsw_afa_block *block,
1809
+ u32 fa_index, u64 rate_bytes_ps, u32 burst,
1810
+ u16 *p_policer_index,
1811
+ struct netlink_ext_ack *extack)
1812
+{
1813
+ struct mlxsw_afa_policer_ref *policer_ref;
1814
+ char *act;
1815
+ int err;
1816
+
1817
+ policer_ref = mlxsw_afa_policer_ref_create(block, fa_index,
1818
+ rate_bytes_ps,
1819
+ burst, extack);
1820
+ if (IS_ERR(policer_ref))
1821
+ return PTR_ERR(policer_ref);
1822
+ *p_policer_index = policer_ref->policer->policer_index;
1823
+
1824
+ act = mlxsw_afa_block_append_action_ext(block, MLXSW_AFA_POLCNT_CODE,
1825
+ MLXSW_AFA_POLCNT_SIZE,
1826
+ MLXSW_AFA_ACTION_TYPE_POLICE);
1827
+ if (IS_ERR(act)) {
1828
+ NL_SET_ERR_MSG_MOD(extack, "Cannot append police action");
1829
+ err = PTR_ERR(act);
1830
+ goto err_append_action;
1831
+ }
1832
+ mlxsw_afa_polcnt_policer_pack(act, *p_policer_index);
1833
+
1834
+ return 0;
1835
+
1836
+err_append_action:
1837
+ mlxsw_afa_policer_ref_destroy(block, policer_ref);
1838
+ return err;
1839
+}
1840
+EXPORT_SYMBOL(mlxsw_afa_block_append_police);
11161841
11171842 /* Virtual Router and Forwarding Domain Action
11181843 * -------------------------------------------
....@@ -1231,3 +1956,54 @@
12311956 return 0;
12321957 }
12331958 EXPORT_SYMBOL(mlxsw_afa_block_append_mcrouter);
1959
+
1960
+/* L4 Port Action
1961
+ * --------------
1962
+ * The L4_PORT_ACTION is used for modifying the sport and dport fields of the packet, e.g. for NAT.
1963
+ * If (the L4 is TCP) or if (the L4 is UDP and checksum field!=0) then the L4 checksum is updated.
1964
+ */
1965
+
1966
+#define MLXSW_AFA_L4PORT_CODE 0x12
1967
+#define MLXSW_AFA_L4PORT_SIZE 1
1968
+
1969
+enum mlxsw_afa_l4port_s_d {
1970
+ /* configure src_l4_port */
1971
+ MLXSW_AFA_L4PORT_S_D_SRC,
1972
+ /* configure dst_l4_port */
1973
+ MLXSW_AFA_L4PORT_S_D_DST,
1974
+};
1975
+
1976
+/* afa_l4port_s_d
1977
+ * Source or destination.
1978
+ */
1979
+MLXSW_ITEM32(afa, l4port, s_d, 0x00, 31, 1);
1980
+
1981
+/* afa_l4port_l4_port
1982
+ * Number of port to change to.
1983
+ */
1984
+MLXSW_ITEM32(afa, l4port, l4_port, 0x08, 0, 16);
1985
+
1986
+static void mlxsw_afa_l4port_pack(char *payload, enum mlxsw_afa_l4port_s_d s_d, u16 l4_port)
1987
+{
1988
+ mlxsw_afa_l4port_s_d_set(payload, s_d);
1989
+ mlxsw_afa_l4port_l4_port_set(payload, l4_port);
1990
+}
1991
+
1992
+int mlxsw_afa_block_append_l4port(struct mlxsw_afa_block *block, bool is_dport, u16 l4_port,
1993
+ struct netlink_ext_ack *extack)
1994
+{
1995
+ enum mlxsw_afa_l4port_s_d s_d = is_dport ? MLXSW_AFA_L4PORT_S_D_DST :
1996
+ MLXSW_AFA_L4PORT_S_D_SRC;
1997
+ char *act = mlxsw_afa_block_append_action(block,
1998
+ MLXSW_AFA_L4PORT_CODE,
1999
+ MLXSW_AFA_L4PORT_SIZE);
2000
+
2001
+ if (IS_ERR(act)) {
2002
+ NL_SET_ERR_MSG_MOD(extack, "Cannot append L4_PORT action");
2003
+ return PTR_ERR(act);
2004
+ }
2005
+
2006
+ mlxsw_afa_l4port_pack(act, s_d, l4_port);
2007
+ return 0;
2008
+}
2009
+EXPORT_SYMBOL(mlxsw_afa_block_append_l4port);