162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2016, Amir Vadai <amir@vadai.me>
462306a36Sopenharmony_ci * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __NET_TC_TUNNEL_KEY_H
862306a36Sopenharmony_ci#define __NET_TC_TUNNEL_KEY_H
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <net/act_api.h>
1162306a36Sopenharmony_ci#include <linux/tc_act/tc_tunnel_key.h>
1262306a36Sopenharmony_ci#include <net/dst_metadata.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistruct tcf_tunnel_key_params {
1562306a36Sopenharmony_ci	struct rcu_head		rcu;
1662306a36Sopenharmony_ci	int			tcft_action;
1762306a36Sopenharmony_ci	struct metadata_dst     *tcft_enc_metadata;
1862306a36Sopenharmony_ci};
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistruct tcf_tunnel_key {
2162306a36Sopenharmony_ci	struct tc_action	      common;
2262306a36Sopenharmony_ci	struct tcf_tunnel_key_params __rcu *params;
2362306a36Sopenharmony_ci};
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define to_tunnel_key(a) ((struct tcf_tunnel_key *)a)
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistatic inline bool is_tcf_tunnel_set(const struct tc_action *a)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci#ifdef CONFIG_NET_CLS_ACT
3062306a36Sopenharmony_ci	struct tcf_tunnel_key *t = to_tunnel_key(a);
3162306a36Sopenharmony_ci	struct tcf_tunnel_key_params *params;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	params = rcu_dereference_protected(t->params,
3462306a36Sopenharmony_ci					   lockdep_is_held(&a->tcfa_lock));
3562306a36Sopenharmony_ci	if (a->ops && a->ops->id == TCA_ID_TUNNEL_KEY)
3662306a36Sopenharmony_ci		return params->tcft_action == TCA_TUNNEL_KEY_ACT_SET;
3762306a36Sopenharmony_ci#endif
3862306a36Sopenharmony_ci	return false;
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic inline bool is_tcf_tunnel_release(const struct tc_action *a)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci#ifdef CONFIG_NET_CLS_ACT
4462306a36Sopenharmony_ci	struct tcf_tunnel_key *t = to_tunnel_key(a);
4562306a36Sopenharmony_ci	struct tcf_tunnel_key_params *params;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	params = rcu_dereference_protected(t->params,
4862306a36Sopenharmony_ci					   lockdep_is_held(&a->tcfa_lock));
4962306a36Sopenharmony_ci	if (a->ops && a->ops->id == TCA_ID_TUNNEL_KEY)
5062306a36Sopenharmony_ci		return params->tcft_action == TCA_TUNNEL_KEY_ACT_RELEASE;
5162306a36Sopenharmony_ci#endif
5262306a36Sopenharmony_ci	return false;
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistatic inline struct ip_tunnel_info *tcf_tunnel_info(const struct tc_action *a)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci#ifdef CONFIG_NET_CLS_ACT
5862306a36Sopenharmony_ci	struct tcf_tunnel_key *t = to_tunnel_key(a);
5962306a36Sopenharmony_ci	struct tcf_tunnel_key_params *params;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	params = rcu_dereference_protected(t->params,
6262306a36Sopenharmony_ci					   lockdep_is_held(&a->tcfa_lock));
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	return &params->tcft_enc_metadata->u.tun_info;
6562306a36Sopenharmony_ci#else
6662306a36Sopenharmony_ci	return NULL;
6762306a36Sopenharmony_ci#endif
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic inline struct ip_tunnel_info *
7162306a36Sopenharmony_citcf_tunnel_info_copy(const struct tc_action *a)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci#ifdef CONFIG_NET_CLS_ACT
7462306a36Sopenharmony_ci	struct ip_tunnel_info *tun = tcf_tunnel_info(a);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	if (tun) {
7762306a36Sopenharmony_ci		size_t tun_size = sizeof(*tun) + tun->options_len;
7862306a36Sopenharmony_ci		struct ip_tunnel_info *tun_copy = kmemdup(tun, tun_size,
7962306a36Sopenharmony_ci							  GFP_ATOMIC);
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci		return tun_copy;
8262306a36Sopenharmony_ci	}
8362306a36Sopenharmony_ci#endif
8462306a36Sopenharmony_ci	return NULL;
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci#endif /* __NET_TC_TUNNEL_KEY_H */
87