On Wed, Aug 20, 2014 at 09:49:41AM +0300, Matan Barak wrote: > +#define MAX(a, b) ((a) > (b) ? (a) : (b)) > +#define MIN(a, b) ((a) < (b) ? (a) : (b)) > +#define print_hdr PFX "resolver: " > +#define print_err(...) fprintf(stderr, print_hdr __VA_ARGS__)
System libraries should really not be printing things on error paths... > +static int set_link_port(union sktaddr *s, int port, int oif) > +{ > + switch (s->s.sa_family) { > + case AF_INET: > + s->s4.sin_port = port; > + break; > + case AF_INET6: > + s->s6.sin6_port = port; > + s->s6.sin6_scope_id = oif; Does flowlabel get initialized someplace? > +static int cmp_address(const struct sockaddr *s1, > + const struct sockaddr *s2) { 'cmp' functions that only test equality should return bool for clarity. Otherwise people will assume the usual -1,0,1 return style, which this does not implement. > + if (s1->sa_family != s2->sa_family) > + return s1->sa_family ^ s2->sa_family; Ditch the ^ for compare, pointless. > +static struct nl_addr *get_neigh_mac(struct get_neigh_handler *neigh_handler) > +{ > + struct rtnl_neigh *neigh; > + struct nl_addr *ll_addr = NULL; > + > + /* future optimization - if link local address - parse address and > + * return mac */ What does this comment refer to? MACs should never be parsed out of IPv6 addresses. > + sock_fd = socket(addr_dst->sktaddr.s.sa_family, > + SOCK_DGRAM | SOCK_CLOEXEC, 0); > + if (sock_fd == -1) > + return errno ? -errno : -1; If socket fails then errno is always set, not sure the safety test is necessary, if it is, then -1 is not the right result, it should be -EINVAL or something. > + err = bind(sock_fd, &addr_src.sktaddr.s, addr_src.len); > + if (err) { > + int bind_err = -errno; > + print_err("Couldn't bind socket\n"); > + close(sock_fd); > + return bind_err ?: err; bind does not return an errno code, so it should never be the return result. > + timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); > + if (-1 == timer_fd) { > + print_err("Couldn't create timer\n"); > + return timer_fd; > + } The use of timerfd will impact the minimum OS version, have you checked this is OK? Does RHEL5 still work? > + while (1) { > + FD_ZERO(&fdset); > + FD_SET(fd, &fdset); > + FD_SET(timer_fd, &fdset); > + > + /* wait for an incoming message on the netlink socket */ > + ret = select(nfds, &fdset, NULL, NULL, NULL); poll is a better choice here, it would also be fairly simple to remove timerfd by using the timeout arg. > + if (sendto(sock_fd, buff, sizeof(buff), > + 0, &addr_dst.sktaddr.s, > + addr_dst.len) < 0) > + print_err("Failed to send " > + "packet while waiting" > + " for > events\n"); If the earlier sendto needs to be protected by a loop looking at EADDRNOTAVAIL then so does this one. I'm also not sure all this looping and complexity is needed... Why override the kernel timers for ND? I would think you'd check the ND table, if there is no good entry then do the send, and then watch the ND table for a FAILED/REACHABLE result. The kernel timers will always transition through INCOMPLETE to one of those terminal states. No need for more timers and retry and things, the kernel already retried. > +static int get_mcast_mac_ipv6(struct nl_addr *dst, struct nl_addr **ll_addr) > +{ > + char mac_addr[6] = {0x33, 0x33}; > + memcpy(mac_addr + 2, (char *)nl_addr_get_binary_addr(dst) + 12, 4); (char *) should be (uint8_t *), you are not working with a string here. Similarly for nearly all char casts. Proper use of const throughout would be nice too.. > +const struct encoded_l3_addr { Missing static > +int nl_addr_cmp_prefix_msb(void *addr1, int len1, void *addr2, int len2) > +{ Missing static > + struct rtnl_nexthop *nh = rtnl_route_nexthop_n(route, 0); > + if (!nh) > + print_err("Out of memory\n"); > + gateway = rtnl_route_nh_get_gateway(nh); And then crash? > +err_link: > + rtnl_link_put(link); > +err: > + if (neigh_handler->src) { > +#ifdef HAVE_LIBNL1 > + nl_addr_put(neigh_handler->src); Should this be nl_addr_destroy ? Can you do a better job with these ifdefs? I think you can get away with a nl1_compat.h which has simple wrapper things like this: static inline void emulate_nl_addr_put(x) {return nl_addr_destroy(x);} #define nl_addr_put(x) emulate_nl_addr_put(x) And purge the ifdefery from the main source. > + > + last_status = __sync_fetch_and_or( > + &neigh_handler->neigh_status, > + GET_NEIGH_STATUS_IN_PROCESS); Is there a thread running around in here someplace? Callina raw gcc intrinsic like this should really be avoided, especially since this isn't a performance path. Use pthreads. > +static inline int ipv6_addr_v4mapped(const struct in6_addr *a) > +{ > + return ((a->s6_addr32[0] | a->s6_addr32[1]) | > + (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0UL || > + /* IPv4 encoded multicast addresses */ > + (a->s6_addr32[0] == htonl(0xff0e0000) && > + ((a->s6_addr32[1] | > + (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0UL)); > +} Don't duplicate IN6_IS_ADDR_V4MAPPED > + if (err) { > + fprintf(stderr, PFX "ibv_create_ah failed to query > sgid.\n"); Again, system libraries should not be printing on error, use errno properly. > +#else > + return -ENOIMPL; Is that a typo of ENOSYS? Be sure you have tested compiling with each and every variation of the #ifdefs added. Jason -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html