int myri_header_cache(struct neighbour *neigh, struct hh_cache *hh)
{
unsigned short type = hh->hh_type;
- unsigned char *pad = (unsigned char *) hh->hh_data;
- struct ethhdr *eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
+ unsigned char *pad;
+ struct ethhdr *eth;
struct net_device *dev = neigh->dev;
+ pad = ((unsigned char *) hh->hh_data) +
+ HH_DATA_OFF(sizeof(*eth) + MYRI_PAD_LEN);
+ eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
+
if (type == __constant_htons(ETH_P_802_3))
return -1;
/* Called by Address Resolution module to notify changes in address. */
void myri_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr)
{
- memcpy(((u8*)hh->hh_data) + 2, haddr, dev->addr_len);
+ memcpy(((u8*)hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)),
+ haddr, dev->addr_len);
}
static int myri_change_mtu(struct net_device *dev, int new_mtu)
if ((ret = nl->orig_hard_header_cache(neigh, hh)) == 0)
{
- struct ethhdr *eth = (struct ethhdr*)(((u8*)hh->hh_data) + 2);
+ struct ethhdr *eth;
+
+ eth = (struct ethhdr*)(((u8*)hh->hh_data) +
+ HH_DATA_OFF(sizeof(*eth)));
plip_rewrite_address (neigh->dev, eth);
}
int hh_len; /* length of header */
int (*hh_output)(struct sk_buff *skb);
rwlock_t hh_lock;
+
/* cached hardware header; allow for machine alignment needs. */
- unsigned long hh_data[16/sizeof(unsigned long)];
+#define HH_DATA_MOD 16
+#define HH_DATA_OFF(__len) \
+ (HH_DATA_MOD - ((__len) & (HH_DATA_MOD - 1)))
+#define HH_DATA_ALIGN(__len) \
+ (((__len)+(HH_DATA_MOD-1))&~(HH_DATA_MOD - 1))
+ unsigned long hh_data[HH_DATA_ALIGN(LL_MAX_HEADER)];
};
/* These flag bits are private to the generic network queueing
int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh)
{
unsigned short type = hh->hh_type;
- struct ethhdr *eth = (struct ethhdr*)(((u8*)hh->hh_data) + 2);
+ struct ethhdr *eth;
struct net_device *dev = neigh->dev;
+ eth = (struct ethhdr*)
+ (((u8*)hh->hh_data) + (HH_DATA_OFF(sizeof(*eth))));
+
if (type == __constant_htons(ETH_P_802_3))
return -1;
void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr)
{
- memcpy(((u8*)hh->hh_data) + 2, haddr, dev->addr_len);
+ memcpy(((u8*)hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)),
+ haddr, dev->addr_len);
}
#endif /*CONFIG_NETFILTER_DEBUG*/
if (hh) {
+ int hh_alen;
+
read_lock_bh(&hh->hh_lock);
- memcpy(skb->data - 16, hh->hh_data, 16);
+ hh_alen = HH_DATA_ALIGN(hh->hh_len);
+ memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
read_unlock_bh(&hh->hh_lock);
skb_push(skb, hh->hh_len);
return hh->hh_output(skb);
struct hh_cache *hh = dst->hh;
if (hh) {
+ int hh_alen;
+
read_lock_bh(&hh->hh_lock);
- memcpy(skb->data - 16, hh->hh_data, 16);
+ hh_alen = HH_DATA_ALIGN(hh->hh_len);
+ memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
read_unlock_bh(&hh->hh_lock);
skb_push(skb, hh->hh_len);
hh->hh_output(skb);
struct hh_cache *hh = dst->hh;
if (hh) {
+ int hh_alen;
+
read_lock_bh(&hh->hh_lock);
- memcpy(skb->data - 16, hh->hh_data, 16);
+ hh_alen = HH_DATA_ALIGN(hh->hh_len);
+ memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);
read_unlock_bh(&hh->hh_lock);
skb_push(skb, hh->hh_len);
return hh->hh_output(skb);