blob: 7efd1cab4ffd6d8defec9dfe9e4c5567d55418da [file] [log] [blame]
#ifndef MCTCP_SAURON_H
#define MCTCP_SAURON_H
#include <linux/rculist.h>
#if defined(CONFIG_MCPS_GRO_PER_SESSION)
#include <linux/skbuff.h>
#endif // #if defined(CONFIG_MCPS_GRO_PER_SESSION)
#ifdef CONFIG_MCPS_DEBUG
#include <uapi/linux/in6.h>
#include <linux/time.h>
#include <linux/timekeeping.h>
#endif // #ifdef CONFIG_MCPS_DEBUG
#include "mcps_buffer.h"
#define sauron_eyes_bits 9
#define sauron_eyes_num (1<<sauron_eyes_bits)
#if defined(CONFIG_MCPS_ICGB)
enum {
EYE_POLICY_FAST = 0,
EYE_POLICY_SLOW,
};
#endif // #if defined(CONFIG_MCPS_ICGB)
/* struct eye - information structure of packet flow (session)
* Notice : eye must be allocated by zero with kzalloc
*/
struct eye {
u32 hash;
u32 value;
u32 capture;
u32 pps;
u32 cpu;
u32 state;
#if defined(CONFIG_MCPS_GRO_PER_SESSION)
u32 gro_nskb;
u32 gro_tog;
#endif // #if defined(CONFIG_MCPS_GRO_PER_SESSION)
#if defined(CONFIG_MCPS_ICGB)
u32 policy;
#endif // #if defined(CONFIG_MCPS_ICGB)
unsigned int dst_ipv4;
struct in6_addr dst_ipv6;
unsigned int dst_port;
unsigned long t_stamp;
unsigned long t_capture;
int monitored;
struct rcu_head rcu;
struct hlist_node eye_hash_node;
#ifdef CONFIG_MCPS_DEBUG
struct timespec timestamp;
atomic_t input_num;
atomic_t output_num;
atomic_t drop_num;
atomic_t ofo_num;
atomic_t mig_count;
atomic_t l2l_count;
atomic_t l2b_count;
atomic_t b2l_count;
atomic_t b2b_count;
struct timespec mig_1st_time;
struct timespec mig_last_time;
#endif
struct pending_queue pendings;
};
struct sauron {
spinlock_t sauron_eyes_lock;
struct hlist_head sauron_eyes[sauron_eyes_num];
spinlock_t cached_eyes_lock[NR_CPUS];
struct eye *heavy_eyes[NR_CPUS]; // cached_eyes_lock, sauron_eyes_lock(?)
struct eye *light_eyes[NR_CPUS]; // cached_eyes_lock, sauron_eyes_lock(?)
unsigned int flow_cnt_by_cpus[NR_CPUS]; // sauron_eyes_lock
unsigned int target_flow_cnt_by_cpus[NR_CPUS]; // sauron_eyes_lock
};
#define DEFAULT_MONITOR_PPS_THRESHOLD 100 // 1mbps = about 100 pps (mtu 1500)
#define MONITOR_CONDITION(pps) (pps >= DEFAULT_MONITOR_PPS_THRESHOLD)
static inline void sauron_lock(struct sauron *s)
{
spin_lock(&s->sauron_eyes_lock);
}
static inline void sauron_unlock(struct sauron *s)
{
spin_unlock(&s->sauron_eyes_lock);
}
static inline void update_heavy_and_light(struct sauron *sauron, struct eye *eye)
{
int cpu = eye->cpu;
if (!MONITOR_CONDITION(eye->pps))
return;
spin_lock(&sauron->cached_eyes_lock[cpu]);
if (!sauron->heavy_eyes[cpu] || sauron->heavy_eyes[cpu]->pps < eye->pps) {
sauron->heavy_eyes[cpu] = eye;
}
if (!sauron->light_eyes[cpu] || sauron->light_eyes[cpu]->pps > eye->pps) {
sauron->light_eyes[cpu] = eye;
}
spin_unlock(&sauron->cached_eyes_lock[cpu]);
}
static inline void remove_heavy_and_light(struct sauron *sauron, struct eye *eye)
{
int cpu = eye->cpu;
spin_lock(&sauron->cached_eyes_lock[cpu]);
if (sauron->heavy_eyes[cpu] == eye)
sauron->heavy_eyes[cpu] = NULL;
if (sauron->light_eyes[cpu] == eye)
sauron->light_eyes[cpu] = NULL;
spin_unlock(&sauron->cached_eyes_lock[cpu]);
}
struct eye *pick_heavy(struct sauron *sauron, int cpu);
struct eye *pick_light(struct sauron *sauron, int cpu);
struct sauron_statistics {
unsigned int cpu_distribute;
};
DECLARE_PER_CPU(struct sauron_statistics, sauron_stats);
#if defined(CONFIG_MCPS_GRO_PER_SESSION)
struct eye_skb {
unsigned int count;
unsigned int limit;
};
#define EYESKB(skb) ((struct eye_skb *)((skb)->cb))
static inline void mcps_eye_gro_stamp(struct eye *e, struct sk_buff *skb)
{
e->gro_tog = (e->gro_nskb != 0) ? (e->gro_tog+1)%e->gro_nskb : 0;
EYESKB(skb)->limit = e->gro_nskb;
EYESKB(skb)->count = e->gro_tog;
}
static inline int mcps_eye_gro_skip(struct sk_buff *skb)
{
return (EYESKB(skb)->limit == 0);
}
static inline int mcps_eye_gro_flush(struct sk_buff *skb)
{
return (EYESKB(skb)->count == 0);
}
#else // #if defined(CONFIG_MCPS_GRO_PER_SESSION)
#define mcps_eye_gro_stamp(e, skb) do { } while (0)
#define mcps_eye_gro_skip(skb) do { } while (0)
#define mcps_eye_gro_flush(skb) do { } while (0)
#endif // #if defined(CONFIG_MCPS_GRO_PER_SESSION)
/* Declare functions */
void init_mcps_core(void);
void release_mcps_core(void);
int get_arps_cpu(struct sauron *sauron, struct sk_buff *skb);
int get_agro_cpu(struct sauron *sauron, struct sk_buff *skb);
int flush_flows(int force);
struct eye *search_flow(struct sauron *sauron, u32 hash);
int _move_flow(unsigned int hash, unsigned int to);
int migrate_flow(unsigned int from, unsigned int to, unsigned int option);
unsigned int light_cpu(void);
#endif