This is another example action. Signed-off-by: Toshiaki Makita <toshiaki.makita1@xxxxxxxxx> --- 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