From d91c131dc67e492dd6ebe3d8172f14d03f8900ae Mon Sep 17 00:00:00 2001 From: francescomessina Date: Mon, 17 Jun 2019 16:15:27 +0200 Subject: [PATCH] removed the old Ip address on the interface in the namespace, when the Ip address is updated in polycube Signed-off-by: francescomessina --- src/polycubed/src/utils/netlink.cpp | 56 +++++++++++++++++++++++++++ src/polycubed/src/utils/netlink.h | 2 + src/services/pcn-router/src/Ports.cpp | 18 +++++++++ 3 files changed, 76 insertions(+) diff --git a/src/polycubed/src/utils/netlink.cpp b/src/polycubed/src/utils/netlink.cpp index 897634ef6..37d705220 100644 --- a/src/polycubed/src/utils/netlink.cpp +++ b/src/polycubed/src/utils/netlink.cpp @@ -668,6 +668,26 @@ struct nlmsghdr* Netlink::netlink_ip_alloc() { return nlmsg; } +struct nlmsghdr* Netlink::netlink_ip_dealloc() { + size_t len = NLMSG_ALIGN(SIZE_ALIGN) + NLMSG_ALIGN(sizeof(struct nlmsghdr *)); + struct nlmsghdr *nlmsg = (struct nlmsghdr *) malloc(len); + memset(nlmsg, 0, len); + + struct nl_ipreq *uni = (struct nl_ipreq *)nlmsg; + uni->ifaddrmsg.ifa_family = AF_INET; + uni->ifaddrmsg.ifa_scope = 0; + + nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + nlmsg->nlmsg_type = RTM_DELADDR; + // NLM_F_REQUEST Must be set on all request messages + // NLM_F_ACK Request for an acknowledgment on success + // NLM_F_CREATE Create object if it doesn't already exist + // NLM_F_EXCL Don't replace if the object already exists + nlmsg->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL; + + return nlmsg; +} + struct nlmsghdr* Netlink::netlink_ipv6_alloc() { size_t len = NLMSG_ALIGN(SIZE_ALIGN) + NLMSG_ALIGN(sizeof(struct nlmsghdr *)); struct nlmsghdr *nlmsg = (struct nlmsghdr *) malloc(len); @@ -845,6 +865,42 @@ void Netlink::set_iface_ip(const std::string &iface, const std::string &ip, int netlink_nl_send(nlmsg); } +void Netlink::unset_iface_ip(const std::string &iface, const std::string &ip, int prefix) { + struct nlmsghdr *nlmsg = netlink_ip_dealloc(); + struct nl_ipreq *uni = (struct nl_ipreq *)nlmsg; + struct rtattr *rta; + struct in_addr ia; + + int index = get_iface_index(iface); + if (index == -1) { + logger->error("unset_iface_ip: iface {0} does not exist", iface); + throw std::runtime_error("unset_iface_ip: iface does not exist"); + } + + uni->ifaddrmsg.ifa_index = index; + uni->ifaddrmsg.ifa_prefixlen = prefix; + + if (inet_pton(AF_INET, ip.c_str(), &ia) <= 0) { + free(nlmsg); + logger->error("unset_iface_ip: Error in inet_pton"); + throw std::runtime_error("unset_iface_ip: Error in inet_pton"); + } + + rta = NLMSG_TAIL(nlmsg); + rta->rta_type = IFA_LOCAL; + rta->rta_len = RTA_LENGTH(sizeof(struct in_addr)); + memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr)); + nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len); + + rta = NLMSG_TAIL(nlmsg); + rta->rta_type = IFA_ADDRESS; + rta->rta_len = RTA_LENGTH(sizeof(struct in_addr)); + memcpy(RTA_DATA(rta), &ia, sizeof(struct in_addr)); + nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + RTA_ALIGN(rta->rta_len); + + netlink_nl_send(nlmsg); +} + void Netlink::set_iface_ipv6(const std::string &iface, const std::string &ipv6) { struct nlmsghdr *nlmsg = netlink_ipv6_alloc(); struct nl_ipreq *uni = (struct nl_ipreq *)nlmsg; diff --git a/src/polycubed/src/utils/netlink.h b/src/polycubed/src/utils/netlink.h index c563d15a1..aa50f04b3 100644 --- a/src/polycubed/src/utils/netlink.h +++ b/src/polycubed/src/utils/netlink.h @@ -80,6 +80,7 @@ class Netlink { void set_iface_status(const std::string &iface, IFACE_STATUS status); void set_iface_mac(const std::string &iface, const std::string &mac); void set_iface_ip(const std::string &iface, const std::string &ip, int prefix); + void unset_iface_ip(const std::string &iface, const std::string &ip, int prefix); void set_iface_ipv6(const std::string &iface, const std::string &ip); void move_iface_into_ns(const std::string &iface, int fd); @@ -123,6 +124,7 @@ class Netlink { struct nlmsghdr* netlink_alloc(); struct nlmsghdr* netlink_ip_alloc(); + struct nlmsghdr* netlink_ip_dealloc(); struct nlmsghdr* netlink_ipv6_alloc(); int netlink_nl_send(struct nlmsghdr *nlmsg); diff --git a/src/services/pcn-router/src/Ports.cpp b/src/services/pcn-router/src/Ports.cpp index 9685a7f97..25b575210 100644 --- a/src/services/pcn-router/src/Ports.cpp +++ b/src/services/pcn-router/src/Ports.cpp @@ -146,8 +146,17 @@ std::string Ports::getIp() { void Ports::setIp(const std::string &value) { // This method set the ip value. if (ip_ != value) { + // unset old ip + if (parent_.get_shadow()) { + int prefix = get_netmask_length(getNetmask()); + std::function doThis = [&]{parent_.netlink_instance_router_.unset_iface_ip(getName(), ip_, prefix);}; + polycube::polycubed::Namespace namespace_ = polycube::polycubed::Namespace::open("pcn-" + parent_.get_name()); + namespace_.execute(doThis); + } + setIp_Netlink(value); + // set new ip if (parent_.get_shadow()) { int prefix = get_netmask_length(getNetmask()); std::function doThis = [&]{parent_.netlink_instance_router_.set_iface_ip(getName(), value, prefix);}; @@ -192,8 +201,17 @@ std::string Ports::getNetmask() { void Ports::setNetmask(const std::string &value) { // This method set the netmask value. if (netmask_ != value) { + // unset old netmask + if (parent_.get_shadow()) { + int prefix = get_netmask_length(netmask_); + std::function doThis = [&]{parent_.netlink_instance_router_.unset_iface_ip(getName(), ip_, prefix);}; + polycube::polycubed::Namespace namespace_ = polycube::polycubed::Namespace::open("pcn-" + parent_.get_name()); + namespace_.execute(doThis); + } + setNetmask_Netlink(value); + // set new netmask if (parent_.get_shadow()) { int prefix = get_netmask_length(value); std::function doThis = [&]{parent_.netlink_instance_router_.set_iface_ip(getName(), getIp(), prefix);};