This is another example action.

Signed-off-by: Toshiaki Makita <toshiaki.maki...@gmail.com>
---
 net/xdp_flow/xdp_flow_kern_bpf.c | 23 +++++++++++++++++++++--
 net/xdp_flow/xdp_flow_kern_mod.c |  5 +++++
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/net/xdp_flow/xdp_flow_kern_bpf.c b/net/xdp_flow/xdp_flow_kern_bpf.c
index 8f3d359..51e181b 100644
--- a/net/xdp_flow/xdp_flow_kern_bpf.c
+++ b/net/xdp_flow/xdp_flow_kern_bpf.c
@@ -90,10 +90,29 @@ static inline int action_redirect(struct xdp_flow_action 
*action)
 static inline int action_vlan_push(struct xdp_md *ctx,
                                   struct xdp_flow_action *action)
 {
+       struct vlan_ethhdr *vehdr;
+       void *data, *data_end;
+       __be16 proto, tci;
+
        account_action(XDP_FLOW_ACTION_VLAN_PUSH);
 
-       // TODO: implement this
-       return XDP_ABORTED;
+       proto = action->vlan.proto;
+       tci = action->vlan.tci;
+
+       if (bpf_xdp_adjust_head(ctx, -VLAN_HLEN))
+               return XDP_DROP;
+
+       data_end = (void *)(long)ctx->data_end;
+       data = (void *)(long)ctx->data;
+       if (data + VLAN_ETH_HLEN > data_end)
+               return XDP_DROP;
+
+       __builtin_memmove(data, data + VLAN_HLEN, ETH_ALEN * 2);
+       vehdr = data;
+       vehdr->h_vlan_proto = proto;
+       vehdr->h_vlan_TCI = tci;
+
+       return _XDP_CONTINUE;
 }
 
 static inline int action_vlan_pop(struct xdp_md *ctx,
diff --git a/net/xdp_flow/xdp_flow_kern_mod.c b/net/xdp_flow/xdp_flow_kern_mod.c
index caa4968..52dc64e 100644
--- a/net/xdp_flow/xdp_flow_kern_mod.c
+++ b/net/xdp_flow/xdp_flow_kern_mod.c
@@ -55,6 +55,11 @@ static int xdp_flow_parse_actions(struct xdp_flow_actions 
*actions,
                        action->ifindex = act->dev->ifindex;
                        break;
                case FLOW_ACTION_VLAN_PUSH:
+                       action->id = XDP_FLOW_ACTION_VLAN_PUSH;
+                       action->vlan.tci = act->vlan.vid |
+                                          (act->vlan.prio << VLAN_PRIO_SHIFT);
+                       action->vlan.proto = act->vlan.proto;
+                       break;
                case FLOW_ACTION_VLAN_POP:
                case FLOW_ACTION_VLAN_MANGLE:
                case FLOW_ACTION_MANGLE:
-- 
1.8.3.1

Reply via email to