|
@@ -34,6 +34,7 @@
|
|
|
|
|
|
#include <net/tc_act/tc_gact.h>
|
|
|
#include <net/tc_act/tc_mirred.h>
|
|
|
+#include <net/tc_act/tc_vlan.h>
|
|
|
|
|
|
#include "cxgb4.h"
|
|
|
#include "cxgb4_tc_flower.h"
|
|
@@ -185,6 +186,27 @@ static void cxgb4_process_flow_actions(struct net_device *in,
|
|
|
|
|
|
fs->action = FILTER_SWITCH;
|
|
|
fs->eport = pi->port_id;
|
|
|
+ } else if (is_tcf_vlan(a)) {
|
|
|
+ u32 vlan_action = tcf_vlan_action(a);
|
|
|
+ u8 prio = tcf_vlan_push_prio(a);
|
|
|
+ u16 vid = tcf_vlan_push_vid(a);
|
|
|
+ u16 vlan_tci = (prio << VLAN_PRIO_SHIFT) | vid;
|
|
|
+
|
|
|
+ switch (vlan_action) {
|
|
|
+ case TCA_VLAN_ACT_POP:
|
|
|
+ fs->newvlan |= VLAN_REMOVE;
|
|
|
+ break;
|
|
|
+ case TCA_VLAN_ACT_PUSH:
|
|
|
+ fs->newvlan |= VLAN_INSERT;
|
|
|
+ fs->vlan = vlan_tci;
|
|
|
+ break;
|
|
|
+ case TCA_VLAN_ACT_MODIFY:
|
|
|
+ fs->newvlan |= VLAN_REWRITE;
|
|
|
+ fs->vlan = vlan_tci;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -222,6 +244,26 @@ static int cxgb4_validate_flow_actions(struct net_device *dev,
|
|
|
__func__);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
+ } else if (is_tcf_vlan(a)) {
|
|
|
+ u16 proto = be16_to_cpu(tcf_vlan_push_proto(a));
|
|
|
+ u32 vlan_action = tcf_vlan_action(a);
|
|
|
+
|
|
|
+ switch (vlan_action) {
|
|
|
+ case TCA_VLAN_ACT_POP:
|
|
|
+ break;
|
|
|
+ case TCA_VLAN_ACT_PUSH:
|
|
|
+ case TCA_VLAN_ACT_MODIFY:
|
|
|
+ if (proto != ETH_P_8021Q) {
|
|
|
+ netdev_err(dev, "%s: Unsupported vlan proto\n",
|
|
|
+ __func__);
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ netdev_err(dev, "%s: Unsupported vlan action\n",
|
|
|
+ __func__);
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ }
|
|
|
} else {
|
|
|
netdev_err(dev, "%s: Unsupported action\n", __func__);
|
|
|
return -EOPNOTSUPP;
|