diff --git a/.gitignore b/.gitignore index e2a4ac540e..34c78e393a 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ Makefile.in /depcomp /install-sh /missing +/out stamp-h? .deps/ diff --git a/cloudwan-build.sh b/cloudwan-build.sh new file mode 100755 index 0000000000..fd9b816ce1 --- /dev/null +++ b/cloudwan-build.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +PACKAGE=`pwd` +PACKAGE=`basename $PACKAGE` +VERSION=1.0-1 +PKGDIR=${PACKAGE}_${VERSION} + +if [ ! -f /usr/bin/automake ]; then + echo "Error: no automake. Run: sudo apt-get install -y automake" 1>&2 + exit 1 +fi + +if [ ! -f Makefile.in ]; then + ./build_setup + ./configure +fi +make +for dir in out deb +do + mkdir -p $dir || exit 1 + cd $dir +done +mkdir -p $PKGDIR || exit 1 +mkdir -p $PKGDIR/DEBIAN || exit 1 +mkdir -p $PKGDIR/etc || exit 1 +mkdir -p $PKGDIR/etc/keepalived || exit 1 +mkdir -p $PKGDIR/usr || exit 1 +mkdir -p $PKGDIR/usr/sbin || exit 1 +if [ ! -f $PKGDIR/usr/sbin/keepalived ]; then + ln ../../bin/keepalived $PKGDIR/usr/sbin +fi +cat < $PKGDIR/DEBIAN/control +Package: esi-keepalived +Version: $VERSION +Section: base +Priority: required +Architecture: amd64 +Maintainer: NTT Innovation Institute, Inc. +Description: esi-keepalived + Keepalived 2.0.7 modified for ESI +EOF +dpkg-deb --build $PKGDIR diff --git a/keepalived/include/vrrp_if.h b/keepalived/include/vrrp_if.h index 11ab3f3177..d4570e9494 100644 --- a/keepalived/include/vrrp_if.h +++ b/keepalived/include/vrrp_if.h @@ -176,5 +176,6 @@ extern void interface_down(interface_t *); extern void cleanup_lost_interface(interface_t *); extern int recreate_vmac_thread(thread_t *); extern void update_added_interface(interface_t *); +extern int get_master_ifindex(interface_t *); #endif diff --git a/keepalived/vrrp/vrrp.c b/keepalived/vrrp/vrrp.c index 352fba0084..400829e0b6 100644 --- a/keepalived/vrrp/vrrp.c +++ b/keepalived/vrrp/vrrp.c @@ -2614,10 +2614,6 @@ vrrp_complete_instance(vrrp_t * vrrp) vrrp->total_priority = vrrp->base_priority; if (vrrp->wantstate == VRRP_STATE_MAST) { - if (vrrp->nopreempt) { - report_config_error(CONFIG_GENERAL_ERROR, "(%s) Warning - nopreempt will not work with initial state MASTER - clearing", vrrp->iname); - vrrp->nopreempt = false; - } if (vrrp->preempt_delay) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) Warning - preempt delay will not work with initial state MASTER - clearing", vrrp->iname); vrrp->preempt_delay = false; diff --git a/keepalived/vrrp/vrrp_if.c b/keepalived/vrrp/vrrp_if.c index e82363982f..0917ae1c43 100644 --- a/keepalived/vrrp/vrrp_if.c +++ b/keepalived/vrrp/vrrp_if.c @@ -738,11 +738,24 @@ if_leave_vrrp_group(sa_family_t family, int sd, interface_t *ifp) int if_setsockopt_bindtodevice(int *sd, interface_t *ifp) { + int master_ifindex; int ret; if (*sd < 0) return -1; + /* If *ifp belongs to a VRF, *sd must be bound to the VRF + * instead of *ifp. Otherwise no packets will be received. + */ + master_ifindex = get_master_ifindex(ifp); + if (master_ifindex > 0) { + interface_t *master_ifp = if_get_by_ifindex(master_ifindex); + if (master_ifp) { + log_message(LOG_INFO, "%s master %s", IF_NAME(ifp), IF_NAME(master_ifp)); + ifp = master_ifp; + } + } + /* -> inbound processing option * Specify the bound_dev_if. * why IP_ADD_MEMBERSHIP & IP_MULTICAST_IF doesnt set @@ -1189,3 +1202,109 @@ update_added_interface(interface_t *ifp) setup_interface(vrrp); } } + +void +parse_rtattr (struct rtattr *tb[], int max, struct rtattr *rta, int len) +{ + memset(tb, 0, sizeof(struct rtattr*) * (max + 1)); + + while (RTA_OK(rta, len)) { + if ((rta->rta_type <= max) && (!tb[rta->rta_type])) { + tb[rta->rta_type] = rta; + } + rta = RTA_NEXT(rta,len); + } +} + +int +get_master_ifindex(interface_t *ifp) +{ + struct sockaddr_nl them; + struct { + struct nlmsghdr nlh; + struct rtgenmsg g; + } req; + struct iovec iov; + struct msghdr msg; + struct rtattr* tb[IFLA_MAX+1]; + char buf[4096/*16384*/]; + struct nlmsghdr *h; + int msglen; + int s; + int end = 0; + int ifindex = -1; + + if (!ifp) { + return -1; + } + s = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (s < 0) { + log_message(LOG_ERR, "socket()"); + return -1; + } + + memset(&req, 0, sizeof(req)); + req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(req.g)); + req.nlh.nlmsg_type = RTM_GETLINK; + req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_REQUEST|NLM_F_DUMP; + req.nlh.nlmsg_seq = 1; + req.nlh.nlmsg_pid = getpid(); + req.g.rtgen_family = AF_PACKET; + memset(&them, 0, sizeof(them)); + memset(&msg, 0, sizeof(msg)); + them.nl_family = AF_NETLINK; + msg.msg_name = &them; + msg.msg_namelen = sizeof(them); + iov.iov_base = &req.nlh; + iov.iov_len = req.nlh.nlmsg_len; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msglen = sendmsg(s, &msg, 0); + if (msglen < 0) { + log_message(LOG_ERR, "send()"); + goto exit; + } + iov.iov_base = buf; + iov.iov_len = sizeof(buf); + while (!end) { + msglen = recvmsg(s, &msg, 0); + if (msglen < 0) { + log_message(LOG_ERR, "recvmsg(): "); + goto exit; + } + if (msglen == 0) { + log_message(LOG_ERR, "EOF on netlink"); + goto exit; + } + for (h = (struct nlmsghdr*)buf; + NLMSG_OK(h, msglen); h = NLMSG_NEXT(h, msglen)) { + + if (h->nlmsg_type == NLMSG_DONE) { + end = 1; + break; + } + if (h->nlmsg_type == NLMSG_ERROR) { + log_message(LOG_ERR, "nlmsgerr"); + goto exit; + } + if (h->nlmsg_type == RTM_NEWLINK) { + struct ifinfomsg *ifi = NLMSG_DATA(h); + + if ((ifindex_t)ifi->ifi_index == ifp->ifindex) { + log_message(LOG_INFO, "check master: %2d: %s", ifi->ifi_index, ifp->ifname); + + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), h->nlmsg_len); + if (tb[IFLA_MASTER]) { + ifindex = *(int*)RTA_DATA(tb[IFLA_MASTER]); + log_message(LOG_INFO, " found master: %d", ifindex); + goto exit; + } + } + } + } + } + +exit: + close(s); + return ifindex; +}