blob: d79ef0a262edc0369f505ffa8bec1ff132e52b38 [file] [log] [blame]
/**
Copyright (c) 2008 - 2013 Quantenna Communications Inc
All Rights Reserved
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
#ifndef _QDRV_BRIDGE_H_
#define _QDRV_BRIDGE_H_
#include <linux/inetdevice.h>
#include <linux/if_arp.h>
#include <linux/ip.h>
#if defined(CONFIG_IPV6)
#include <net/ipv6.h>
#include <linux/in6.h>
#endif
#include <net80211/if_ethersubr.h>
#include "qdrv_mac.h"
#include "qdrv_soc.h"
#include "qdrv_comm.h"
#define QDRV_BR_ENT_MAX 128 /* unicast clients */
#define QDRV_BR_MCAST_MAX 128 /* multicast addresses & clients */
#define QDRV_BR_MAC_HASH_SIZE 256
#define QDRV_BR_IP_HASH_SIZE 256
struct ether_arp {
struct arphdr ea_hdr; /* fixed-size header */
u_int8_t arp_sha[ETH_ALEN]; /* sender hardware address */
u_int8_t arp_spa[4]; /* sender protocol address */
u_int8_t arp_tha[ETH_ALEN]; /* target hardware address */
u_int8_t arp_tpa[4]; /* target protocol address */
};
/*
* Each bridge table (one per vap) contains:
* - a list of downstream (unicast) clients, keyed by MAC address and IP address hash
* - a list of multicast addresses, keyed by IP address, containing a list of
* subscribed downstream client MAC addresses
* All keys are implemented as hash tables.
*/
struct qdrv_br_uc {
__be32 ip_addr;
unsigned char mac_addr[IEEE80211_ADDR_LEN];
struct hlist_node mac_hlist;
struct hlist_node ip_hlist;
struct rcu_head rcu;
};
struct qdrv_br_mc {
__be32 mc_ip_addr;
atomic_t mc_client_tot;
struct hlist_node mc_hlist;
struct hlist_head mc_client_hash[QDRV_BR_IP_HASH_SIZE];
struct rcu_head rcu;
};
struct qdrv_br_mc_client {
unsigned char mac_addr[IEEE80211_ADDR_LEN];
struct hlist_node mc_client_hlist;
struct rcu_head rcu;
};
#if defined(CONFIG_IPV6)
struct qdrv_br_ipv6_uc {
struct in6_addr ipv6_addr;
unsigned char mac_addr[ETH_ALEN];
struct hlist_node mac_hlist;
struct hlist_node ipv6_hlist;
struct rcu_head rcu;
};
#endif
struct qdrv_br {
spinlock_t uc_lock;
spinlock_t mc_lock;
unsigned long uc_lock_flags;
unsigned long mc_lock_flags;
atomic_t uc_tot;
atomic_t mc_tot; // Total multicast and client entries
struct hlist_head uc_mac_hash[QDRV_BR_MAC_HASH_SIZE];
struct hlist_head uc_ip_hash[QDRV_BR_IP_HASH_SIZE];
struct hlist_head mc_ip_hash[QDRV_BR_IP_HASH_SIZE];
#if defined(CONFIG_IPV6)
struct hlist_head uc_ipv6_hash[QDRV_BR_IP_HASH_SIZE];
atomic_t uc_ipv6_tot;
spinlock_t uc_ipv6_lock;
unsigned long uc_ipv6_lock_flags;
#endif
};
void qdrv_br_create(struct qdrv_br *br);
void qdrv_br_exit(struct qdrv_br *br);
void qdrv_br_delete(struct qdrv_br *br);
void qdrv_br_show(struct qdrv_br *br);
void qdrv_br_clear(struct qdrv_br *br);
void qdrv_br_uc_update_from_dhcp(struct qdrv_br *br, struct sk_buff *skb,
struct iphdr *iphdr_p);
void qdrv_br_uc_update_from_arp(struct qdrv_br *br, struct ether_arp *arp);
int qdrv_br_mc_update_from_igmp(struct qdrv_br *br, struct sk_buff *skb,
struct ether_header *eh, struct iphdr *iphdr_p);
#if defined(CONFIG_IPV6)
void qdrv_br_ipv6uc_update_from_icmpv6(struct qdrv_br *br,
const struct ethhdr *eth,
const struct ipv6hdr *ipv6h,
const struct icmp6hdr *icmpv6h);
#endif
int qdrv_br_set_dest_mac(struct qdrv_br *br, struct ether_header *eh, const struct sk_buff *skb);
#endif