2010/8/11 Simon Horman <[email protected]>: >> > http://hg.linux-ha.org/agents/rev/612e2966f372 >> >> I've had to commit a small revision, because on IA64, the memory on the >> stack is not aligned properly for the cast to struct nd_neighbor_advert >> * - http://hg.linux-ha.org/agents/rev/d206bc8f1303 >> >> I apologize for the uglyness; it was the only way I could make gcc >> shutup and get the alignment right. If someone can make the alignment >> properly on the stack, I'm all ears ... > > You are right, that is a bit ugly. > But I have no better ideas at this time :-(
How about this patch or along this line? It assumes GCC but ICC should have a similar feature if you want to support it. Alternatively, having an union with an u_int8_t array and a struct should make an alignment correctly, I think. -- Keisuke MORI
# HG changeset patch # User Keisuke MORI <[email protected]> # Date 1281491442 -32400 # Node ID b12ca86af66197498cbf537ccc7ad4ff56cdf63b # Parent d206bc8f13039b332e76a93a86e8e550b67781da [mq]: ipv6addr-alignment.patch diff -r d206bc8f1303 -r b12ca86af661 heartbeat/IPv6addr.c --- a/heartbeat/IPv6addr.c Mon Aug 09 21:51:19 2010 +0200 +++ b/heartbeat/IPv6addr.c Wed Aug 11 10:50:42 2010 +0900 @@ -89,7 +89,6 @@ #include <stdio.h> #include <stdlib.h> -#include <malloc.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> @@ -424,10 +423,17 @@ int ifindex; int hop; struct ifreq ifr; - u_int8_t *payload; - int payload_size; - struct nd_neighbor_advert *na; - struct nd_opt_hdr *opt; + + /* GCC is assumed. + * If you want to port to other than GCC, make sure that + * the packet is packed correctly. + */ + struct neighbor_advert { + struct nd_neighbor_advert na; + struct nd_opt_hdr opt; + u_int8_t hwaddr[HWADDR_LEN]; + } __attribute__ ((packed)) payload; + struct sockaddr_in6 src_sin6; struct sockaddr_in6 dst_sin6; @@ -473,39 +479,27 @@ } /* build a neighbor advertisement message */ - payload_size = sizeof(struct nd_neighbor_advert) - + sizeof(struct nd_opt_hdr) + HWADDR_LEN; - payload = memalign(sysconf(_SC_PAGESIZE), payload_size); - if (!payload) { - cl_log(LOG_ERR, "malloc for payload failed"); - goto err; - } - memset(payload, 0, payload_size); + memset((void *)&payload, 0, sizeof(payload)); - /* Ugly typecast from ia64 hell! */ - na = (struct nd_neighbor_advert *)((void *)payload); - na->nd_na_type = ND_NEIGHBOR_ADVERT; - na->nd_na_code = 0; - na->nd_na_cksum = 0; /* calculated by kernel */ - na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE; - na->nd_na_target = *src_ip; + payload.na.nd_na_type = ND_NEIGHBOR_ADVERT; + payload.na.nd_na_code = 0; + payload.na.nd_na_cksum = 0; /* calculated by kernel */ + payload.na.nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE; + payload.na.nd_na_target = *src_ip; /* options field; set the target link-layer address */ - opt = (struct nd_opt_hdr *)(payload + sizeof(struct nd_neighbor_advert)); - opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; - opt->nd_opt_len = 1; /* The length of the option in units of 8 octets */ - memcpy(payload + sizeof(struct nd_neighbor_advert) - + sizeof(struct nd_opt_hdr), - &ifr.ifr_hwaddr.sa_data, HWADDR_LEN); + payload.opt.nd_opt_type = ND_OPT_TARGET_LINKADDR; + payload.opt.nd_opt_len = 1; /* The length of the option in units of 8 octets */ + memcpy(payload.hwaddr, &ifr.ifr_hwaddr.sa_data, HWADDR_LEN); /* sending an unsolicited neighbor advertisement to all */ memset(&dst_sin6, 0, sizeof(dst_sin6)); dst_sin6.sin6_family = AF_INET6; inet_pton(AF_INET6, BCAST_ADDR, &dst_sin6.sin6_addr); /* should not fail */ - if (sendto(fd, payload, payload_size, 0, + if (sendto(fd, (void *)&payload, sizeof(payload), 0, (struct sockaddr *)&dst_sin6, sizeof(dst_sin6)) - != payload_size) { + != sizeof(payload)) { cl_log(LOG_ERR, "sendto(%s) failed: %s", if_name, strerror(errno)); goto err; @@ -515,7 +509,6 @@ err: close(fd); - free(payload); return status; }
_______________________________________________________ Linux-HA-Dev: [email protected] http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev Home Page: http://linux-ha.org/
