root/include/net/tc_act/tc_gate.h
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Copyright 2020 NXP */

#ifndef __NET_TC_GATE_H
#define __NET_TC_GATE_H

#include <net/act_api.h>
#include <linux/tc_act/tc_gate.h>

struct action_gate_entry {
        u8                      gate_state;
        u32                     interval;
        s32                     ipv;
        s32                     maxoctets;
};

struct tcfg_gate_entry {
        int                     index;
        u8                      gate_state;
        u32                     interval;
        s32                     ipv;
        s32                     maxoctets;
        struct list_head        list;
};

struct tcf_gate_params {
        s32                     tcfg_priority;
        u64                     tcfg_basetime;
        u64                     tcfg_cycletime;
        u64                     tcfg_cycletime_ext;
        u32                     tcfg_flags;
        s32                     tcfg_clockid;
        size_t                  num_entries;
        struct list_head        entries;
        struct rcu_head         rcu;
};

#define GATE_ACT_GATE_OPEN      BIT(0)
#define GATE_ACT_PENDING        BIT(1)

struct tcf_gate {
        struct tc_action        common;
        struct tcf_gate_params __rcu *param;
        u8                      current_gate_status;
        ktime_t                 current_close_time;
        u32                     current_entry_octets;
        s32                     current_max_octets;
        struct tcfg_gate_entry  *next_entry;
        struct hrtimer          hitimer;
        enum tk_offsets         tk_offset;
};

#define to_gate(a) ((struct tcf_gate *)a)

static inline struct tcf_gate_params *tcf_gate_params_locked(const struct tc_action *a)
{
        struct tcf_gate *gact = to_gate(a);

        return rcu_dereference_protected(gact->param,
                                         lockdep_is_held(&gact->tcf_lock));
}

static inline s32 tcf_gate_prio(const struct tc_action *a)
{
        struct tcf_gate_params *p;
        s32 tcfg_prio;

        p = tcf_gate_params_locked(a);
        tcfg_prio = p->tcfg_priority;

        return tcfg_prio;
}

static inline u64 tcf_gate_basetime(const struct tc_action *a)
{
        struct tcf_gate_params *p;
        u64 tcfg_basetime;

        p = tcf_gate_params_locked(a);
        tcfg_basetime = p->tcfg_basetime;

        return tcfg_basetime;
}

static inline u64 tcf_gate_cycletime(const struct tc_action *a)
{
        struct tcf_gate_params *p;
        u64 tcfg_cycletime;

        p = tcf_gate_params_locked(a);
        tcfg_cycletime = p->tcfg_cycletime;

        return tcfg_cycletime;
}

static inline u64 tcf_gate_cycletimeext(const struct tc_action *a)
{
        struct tcf_gate_params *p;
        u64 tcfg_cycletimeext;

        p = tcf_gate_params_locked(a);
        tcfg_cycletimeext = p->tcfg_cycletime_ext;

        return tcfg_cycletimeext;
}

static inline u32 tcf_gate_num_entries(const struct tc_action *a)
{
        struct tcf_gate_params *p;
        u32 num_entries;

        p = tcf_gate_params_locked(a);
        num_entries = p->num_entries;

        return num_entries;
}

static inline struct action_gate_entry
                        *tcf_gate_get_list(const struct tc_action *a)
{
        struct action_gate_entry *oe;
        struct tcf_gate_params *p;
        struct tcfg_gate_entry *entry;
        u32 num_entries;
        int i = 0;

        p = tcf_gate_params_locked(a);
        num_entries = p->num_entries;

        list_for_each_entry(entry, &p->entries, list)
                i++;

        if (i != num_entries)
                return NULL;

        oe = kzalloc_objs(*oe, num_entries, GFP_ATOMIC);
        if (!oe)
                return NULL;

        i = 0;
        list_for_each_entry(entry, &p->entries, list) {
                oe[i].gate_state = entry->gate_state;
                oe[i].interval = entry->interval;
                oe[i].ipv = entry->ipv;
                oe[i].maxoctets = entry->maxoctets;
                i++;
        }

        return oe;
}
#endif