History

Merge branch 'Offload-tc-vlan-mangle-to-mscc_ocelot-switch'

Vladimir Oltean says: ==================== Offload tc-vlan mangle to mscc_ocelot switch This series offloads one more action to the VCAP IS1 ingress TCAM, which is to change the classified VLAN for packets, according to the VCAP IS1 keys (VLAN, source MAC, source IP, EtherType, etc). ====================

Jakub Kicinski committed 6 years ago

Commit bc081a62 parents bea4b30 82c200b4 files · +119 −6Browse files

Unified · Split

4 files
  1. drivers/net/ethernet/mscc/ocelot.c +14 −1
  2. drivers/net/ethernet/mscc/ocelot_flower.c +26 −3
  3. net/dsa/tag_ocelot.c +34 −0
  4. tools/testing/selftests/drivers/net/ocelot/tc_flower_chains.sh +45 −2
drivers/net/ethernet/mscc/ocelot.c+14−1
@@ -205,8 +205,21 @@ int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, · 204 unmodified lines
205 struct ocelot_port *ocelot_port = ocelot->ports[port];205 struct ocelot_port *ocelot_port = ocelot->ports[port];
206 u32 val;206 u32 val;
207 207
208 if (switchdev_trans_ph_prepare(trans))208 if (switchdev_trans_ph_prepare(trans)) {
209 struct ocelot_vcap_block *block = &ocelot->block[VCAP_IS1];
210 struct ocelot_vcap_filter *filter;
211
212 list_for_each_entry(filter, &block->rules, list) {
213 if (filter->ingress_port_mask & BIT(port) &&
214 filter->action.vid_replace_ena) {
215 dev_err(ocelot->dev,
216 "Cannot change VLAN state with vlan modify rules active\n");
217 return -EBUSY;
218 }
219 }
220
209 return 0;221 return 0;
222 }
210 223
211 ocelot_port->vlan_aware = vlan_aware;224 ocelot_port->vlan_aware = vlan_aware;
212 225
drivers/net/ethernet/mscc/ocelot_flower.c+26−3
@@ -142,10 +142,11 @@ ocelot_find_vcap_filter_that_points_at(struct ocelot *ocelot, int chain) · 141 unmodified lines
142 return NULL;142 return NULL;
143}143}
144 144
145static int ocelot_flower_parse_action(struct ocelot *ocelot, bool ingress,145static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
146 struct flow_cls_offload *f,146 bool ingress, struct flow_cls_offload *f,
147 struct ocelot_vcap_filter *filter)147 struct ocelot_vcap_filter *filter)
148{148{
149 struct ocelot_port *ocelot_port = ocelot->ports[port];
149 struct netlink_ext_ack *extack = f->common.extack;150 struct netlink_ext_ack *extack = f->common.extack;
150 bool allow_missing_goto_target = false;151 bool allow_missing_goto_target = false;
151 const struct flow_action_entry *a;152 const struct flow_action_entry *a;
@@ -266,6 +267,28 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, bool ingress, · 114 unmodified lines
266 }267 }
267 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;268 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
268 break;269 break;
270 case FLOW_ACTION_VLAN_MANGLE:
271 if (filter->block_id != VCAP_IS1) {
272 NL_SET_ERR_MSG_MOD(extack,
273 "VLAN modify action can only be offloaded to VCAP IS1");
274 return -EOPNOTSUPP;
275 }
276 if (filter->goto_target != -1) {
277 NL_SET_ERR_MSG_MOD(extack,
278 "Last action must be GOTO");
279 return -EOPNOTSUPP;
280 }
281 if (!ocelot_port->vlan_aware) {
282 NL_SET_ERR_MSG_MOD(extack,
283 "Can only modify VLAN under VLAN aware bridge");
284 return -EOPNOTSUPP;
285 }
286 filter->action.vid_replace_ena = true;
287 filter->action.pcp_dei_ena = true;
288 filter->action.vid = a->vlan.vid;
289 filter->action.pcp = a->vlan.prio;
290 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
291 break;
269 case FLOW_ACTION_PRIORITY:292 case FLOW_ACTION_PRIORITY:
270 if (filter->block_id != VCAP_IS1) {293 if (filter->block_id != VCAP_IS1) {
271 NL_SET_ERR_MSG_MOD(extack,294 NL_SET_ERR_MSG_MOD(extack,
@@ -601,7 +624,7 @@ static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress, · 329 unmodified lines
601 filter->prio = f->common.prio;624 filter->prio = f->common.prio;
602 filter->id = f->cookie;625 filter->id = f->cookie;
603 626
604 ret = ocelot_flower_parse_action(ocelot, ingress, f, filter);627 ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter);
605 if (ret)628 if (ret)
606 return ret;629 return ret;
607 630
net/dsa/tag_ocelot.c+34−0
@@ -184,9 +184,14 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb, · 183 unmodified lines
184 struct net_device *netdev,184 struct net_device *netdev,
185 struct packet_type *pt)185 struct packet_type *pt)
186{186{
187 struct dsa_port *cpu_dp = netdev->dsa_ptr;
188 struct dsa_switch *ds = cpu_dp->ds;
189 struct ocelot *ocelot = ds->priv;
187 u64 src_port, qos_class;190 u64 src_port, qos_class;
191 u64 vlan_tci, tag_type;
188 u8 *start = skb->data;192 u8 *start = skb->data;
189 u8 *extraction;193 u8 *extraction;
194 u16 vlan_tpid;
190 195
191 /* Revert skb->data by the amount consumed by the DSA master,196 /* Revert skb->data by the amount consumed by the DSA master,
192 * so it points to the beginning of the frame.197 * so it points to the beginning of the frame.
@@ -214,6 +219,8 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb, · 21 unmodified lines
214 219
215 packing(extraction, &src_port, 46, 43, OCELOT_TAG_LEN, UNPACK, 0);220 packing(extraction, &src_port, 46, 43, OCELOT_TAG_LEN, UNPACK, 0);
216 packing(extraction, &qos_class, 19, 17, OCELOT_TAG_LEN, UNPACK, 0);221 packing(extraction, &qos_class, 19, 17, OCELOT_TAG_LEN, UNPACK, 0);
222 packing(extraction, &tag_type, 16, 16, OCELOT_TAG_LEN, UNPACK, 0);
223 packing(extraction, &vlan_tci, 15, 0, OCELOT_TAG_LEN, UNPACK, 0);
217 224
218 skb->dev = dsa_master_find_slave(netdev, 0, src_port);225 skb->dev = dsa_master_find_slave(netdev, 0, src_port);
219 if (!skb->dev)226 if (!skb->dev)
@@ -228,6 +235,33 @@ static struct sk_buff *ocelot_rcv(struct sk_buff *skb, · 8 unmodified lines
228 skb->offload_fwd_mark = 1;235 skb->offload_fwd_mark = 1;
229 skb->priority = qos_class;236 skb->priority = qos_class;
230 237
238 /* Ocelot switches copy frames unmodified to the CPU. However, it is
239 * possible for the user to request a VLAN modification through
240 * VCAP_IS1_ACT_VID_REPLACE_ENA. In this case, what will happen is that
241 * the VLAN ID field from the Extraction Header gets updated, but the
242 * 802.1Q header does not (the classified VLAN only becomes visible on
243 * egress through the "port tag" of front-panel ports).
244 * So, for traffic extracted by the CPU, we want to pick up the
245 * classified VLAN and manually replace the existing 802.1Q header from
246 * the packet with it, so that the operating system is always up to
247 * date with the result of tc-vlan actions.
248 * NOTE: In VLAN-unaware mode, we don't want to do that, we want the
249 * frame to remain unmodified, because the classified VLAN is always
250 * equal to the pvid of the ingress port and should not be used for
251 * processing.
252 */
253 vlan_tpid = tag_type ? ETH_P_8021AD : ETH_P_8021Q;
254
255 if (ocelot->ports[src_port]->vlan_aware &&
256 eth_hdr(skb)->h_proto == htons(vlan_tpid)) {
257 u16 dummy_vlan_tci;
258
259 skb_push_rcsum(skb, ETH_HLEN);
260 __skb_vlan_pop(skb, &dummy_vlan_tci);
261 skb_pull_rcsum(skb, ETH_HLEN);
262 __vlan_hwaccel_put_tag(skb, htons(vlan_tpid), vlan_tci);
263 }
264
231 return skb;265 return skb;
232}266}
233 267
tools/testing/selftests/drivers/net/ocelot/tc_flower_chains.sh+45−2
@@ -166,6 +166,9 @@ setup_prepare() · 165 unmodified lines
166 ip link add link $eth3 name $eth3.100 type vlan id 100166 ip link add link $eth3 name $eth3.100 type vlan id 100
167 ip link set $eth3.100 up167 ip link set $eth3.100 up
168 168
169 ip link add link $eth3 name $eth3.200 type vlan id 200
170 ip link set $eth3.200 up
171
169 tc filter add dev $eth0 ingress chain $(IS1 1) pref 1 \172 tc filter add dev $eth0 ingress chain $(IS1 1) pref 1 \
170 protocol 802.1Q flower skip_sw vlan_id 100 \173 protocol 802.1Q flower skip_sw vlan_id 100 \
171 action vlan pop \174 action vlan pop \
@@ -175,12 +178,12 @@ setup_prepare() · 3 unmodified lines
175 flower skip_sw indev $eth1 \178 flower skip_sw indev $eth1 \
176 action vlan push protocol 802.1Q id 100179 action vlan push protocol 802.1Q id 100
177 180
178 tc filter add dev $eth0 ingress chain $(IS1 0) \181 tc filter add dev $eth0 ingress chain $(IS1 0) pref 2 \
179 protocol ipv4 flower skip_sw src_ip 10.1.1.2 \182 protocol ipv4 flower skip_sw src_ip 10.1.1.2 \
180 action skbedit priority 7 \183 action skbedit priority 7 \
181 action goto chain $(IS1 1)184 action goto chain $(IS1 1)
182 185
183 tc filter add dev $eth0 ingress chain $(IS2 0 0) \186 tc filter add dev $eth0 ingress chain $(IS2 0 0) pref 1 \
184 protocol ipv4 flower skip_sw ip_proto udp dst_port 5201 \187 protocol ipv4 flower skip_sw ip_proto udp dst_port 5201 \
185 action police rate 50mbit burst 64k \188 action police rate 50mbit burst 64k \
186 action goto chain $(IS2 1 0)189 action goto chain $(IS2 1 0)
@@ -188,6 +191,7 @@ setup_prepare() · 1 unmodified line
188 191
189cleanup()192cleanup()
190{193{
194 ip link del $eth3.200
191 ip link del $eth3.100195 ip link del $eth3.100
192 tc qdisc del dev $eth0 clsact196 tc qdisc del dev $eth0 clsact
193 ip link del br0197 ip link del br0
@@ -238,6 +242,44 @@ test_vlan_push() · 44 unmodified lines
238 tcpdump_cleanup242 tcpdump_cleanup
239}243}
240 244
245test_vlan_modify()
246{
247 printf "Testing VLAN modification.. "
248
249 ip link set br0 type bridge vlan_filtering 1
250 bridge vlan add dev $eth0 vid 200
251 bridge vlan add dev $eth0 vid 300
252 bridge vlan add dev $eth1 vid 300
253
254 tc filter add dev $eth0 ingress chain $(IS1 2) pref 3 \
255 protocol 802.1Q flower skip_sw vlan_id 200 \
256 action vlan modify id 300 \
257 action goto chain $(IS2 0 0)
258
259 tcpdump_start $eth2
260
261 $MZ $eth3.200 -q -c 1 -p 64 -a $eth3_mac -b $eth2_mac -t ip
262
263 sleep 1
264
265 tcpdump_stop
266
267 if tcpdump_show | grep -q "$eth3_mac > $eth2_mac, .* vlan 300"; then
268 echo "OK"
269 else
270 echo "FAIL"
271 fi
272
273 tcpdump_cleanup
274
275 tc filter del dev $eth0 ingress chain $(IS1 2) pref 3
276
277 bridge vlan del dev $eth0 vid 200
278 bridge vlan del dev $eth0 vid 300
279 bridge vlan del dev $eth1 vid 300
280 ip link set br0 type bridge vlan_filtering 0
281}
282
241test_skbedit_priority()283test_skbedit_priority()
242{284{
243 local num_pkts=100285 local num_pkts=100
@@ -262,6 +304,7 @@ trap cleanup EXIT · 18 unmodified lines
262ALL_TESTS="304ALL_TESTS="
263 test_vlan_pop305 test_vlan_pop
264 test_vlan_push306 test_vlan_push
307 test_vlan_modify
265 test_skbedit_priority308 test_skbedit_priority
266"309"
267 310