blob: 9795e3175c6b9e9542a773cc8f4bbc674a3b3be0 [file] [log] [blame]
/*
*
* Copyright (C) 2007 Mindspeed Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _AUTO_BRIDGE_PRIVATE_H
#define _AUTO_BRIDGE_PRIVATE_H
#define L2FLOW_HASH_TABLE_SIZE 1024
#define L2FLOW_HASH_BY_MAC_TABLE_SIZE 128
#define ABM_DEFAULT_MAX_ENTRIES 5000
/* Internal flags */
#define L2FLOW_FL_NEEDS_UPDATE 0x1
#define L2FLOW_FL_DEAD 0x2
#define L2FLOW_FL_WAIT_ACK 0x4
#define L2FLOW_FL_PENDING_MSG 0x8
enum l2flow_state{
L2FLOW_STATE_SEEN,
L2FLOW_STATE_CONFIRMED,
L2FLOW_STATE_LINUX,
L2FLOW_STATE_FF,
L2FLOW_STATE_DYING, // Intermediate state before effective deletion to give some time to CMM
L2FLOW_STATE_MAX,
};
/* L2flow definition*/
struct l2flow
{
u8 saddr[ETH_ALEN];
u8 daddr[ETH_ALEN];
u16 ethertype;
u16 session_id;
u16 vlan_tag; /* TCI only */
/* L3 info optional */
struct{
union {
u32 all[4];
u32 ip;
u32 ip6[4];
}saddr;
union {
u32 all[4];
u32 ip;
u32 ip6[4];
}daddr;
u8 proto;
}l3;
struct{
/* L4 info optional */
u16 sport;
u16 dport;
}l4;
};
/* L2flow table entry definition*/
struct l2flowTable
{
struct list_head list;
struct list_head list_by_src_mac;
struct list_head list_by_dst_mac;
struct list_head list_wait_for_ack;
struct list_head list_msg_to_send;
unsigned char state;
unsigned long time_sent;
unsigned int flags;
struct timer_list timeout;
u32 idev_ifi;
u32 odev_ifi;
u16 packet_mark;
struct l2flow l2flow;
};
#define ABM_PRINT(type, info, args...) do {printk(type "ABM :" info, ## args);} while(0)
static inline void print_l2flow(struct l2flow *l2flowtmp)
{
ABM_PRINT(KERN_DEBUG, " Saddr : %02x:%02x:%02x:%02x:%02x:%02x\n", l2flowtmp->saddr[0], l2flowtmp->saddr[1], l2flowtmp->saddr[2],
l2flowtmp->saddr[3], l2flowtmp->saddr[4], l2flowtmp->saddr[5]);
ABM_PRINT(KERN_DEBUG, " Daddr : %02x:%02x:%02x:%02x:%02x:%02x\n", l2flowtmp->daddr[0], l2flowtmp->daddr[1], l2flowtmp->daddr[2],
l2flowtmp->daddr[3], l2flowtmp->daddr[4], l2flowtmp->daddr[5]);
ABM_PRINT(KERN_DEBUG, " Ethertype : %04x\n", htons(l2flowtmp->ethertype));
ABM_PRINT(KERN_DEBUG, " PPPoE Session id : %d\n", l2flowtmp->session_id);
}
#if 0
static inline unsigned int abm_l2_flow_hash(u8 *saddr, u8 *daddr, u16 ethertype,
u32 session_id, u32 *ipsaddr, u32 *ipdaddr, u8 proto, u16 sport, u16 dport)
{
u32 a, b, c, d , e;
a = jhash((void *) saddr, 6, ethertype);
b = jhash((void *) daddr, 6, session_id);
c = 0;
d = 0;
if (ethertype == htons(ETH_P_IP))
{
c = jhash_2words(*ipsaddr, *ipdaddr, sport | (dport << 16));
}
else if (ethertype == htons(ETH_P_IPV6))
{
c = jhash2((void *) ipsaddr, 4, sport);
d =jhash2((void *) ipdaddr, 4, dport);
}
return jhash_3words(a, b, c, d);
}
#endif
static inline unsigned int abm_l2flow_hash(struct l2flow *l2flowtmp)
{
return (jhash(l2flowtmp, sizeof(struct l2flow), 0x12345678) & (L2FLOW_HASH_TABLE_SIZE - 1));
}
static inline unsigned int abm_l2flow_hash_mac(char *src_mac)
{
return (jhash(src_mac, ETH_ALEN, 0x12345678) & (L2FLOW_HASH_BY_MAC_TABLE_SIZE - 1));
}
static inline int abm_l2flow_cmp(struct l2flow *flow_a, struct l2flow *flow_b);
static struct l2flowTable * abm_l2flow_find(struct l2flow *l2flowtmp);
static int abm_l2flow_msg_handle(char action, int flags, struct l2flow *l2flowtmp);
static struct l2flowTable * abm_l2flow_add(struct l2flow *l2flowtmp);
static void abm_l2flow_del(struct l2flowTable *l2flow_entry);
static void abm_l2flow_update(int flags, struct l2flowTable *table_entry);
static void abm_l2flow_table_flush(void);
extern void br_fdb_register_can_expire_cb(int(*cb)(unsigned char *mac_addr, struct net_device *dev));
extern void br_fdb_deregister_can_expire_cb(void);
static void abm_do_work_send_msg(struct work_struct *work);
static void abm_do_work_retransmit(struct work_struct *work);
static int abm_nl_send_l2flow_msg(struct sock *s, char action, int flags, struct l2flowTable *table_entry);
static void __abm_go_dying(struct l2flowTable *table_entry);
#endif