[libvirt] [ 3/3] assign peer address if it provided in network

Vasiliy Tolstov v.tolstov at selfip.ru
Fri Mar 18 22:19:43 UTC 2016


Assign peer address if it provided

Signed-off-by: Vasiliy Tolstov <v.tolstov at selfip.ru>
---
 include/libvirt/libvirt-domain.h |  1 +
 src/conf/domain_conf.c           | 14 ++++++++++++-
 src/conf/domain_conf.h           |  1 +
 src/conf/network_conf.c          | 26 +++++++++++++++++++++++-
 src/conf/network_conf.h          |  1 +
 src/lxc/lxc_container.c          |  2 +-
 src/network/bridge_driver.c      |  2 +-
 src/util/virnetdev.c             | 43 +++++++++++++++++++++++++++-------------
 src/util/virnetdev.h             |  1 +
 9 files changed, 73 insertions(+), 18 deletions(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 4ac29cd78816..d2cd45eba253 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -3926,6 +3926,7 @@ typedef virDomainIPAddress *virDomainIPAddressPtr;
 struct _virDomainInterfaceIPAddress {
     int type;                /* virIPAddrType */
     char *addr;              /* IP address */
+    char *peer;              /* IP peer */
     unsigned int prefix;     /* IP address prefix */
 };
 
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7d68096f0e55..fa62cda7a290 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -5725,7 +5725,7 @@ virDomainNetIpParseXML(xmlNodePtr node)
     unsigned int prefixValue = 0;
     char *familyStr = NULL;
     int family = AF_UNSPEC;
-    char *address = NULL;
+    char *address = NULL, *peer = NULL;
 
     if (!(prefixStr = virXMLPropString(node, "prefix")) ||
         (virStrToLong_ui(prefixStr, NULL, 10, &prefixValue) < 0)) {
@@ -5739,6 +5739,9 @@ virDomainNetIpParseXML(xmlNodePtr node)
         goto cleanup;
     }
 
+    if ((peer = virXMLPropString(node, "peer")) == NULL)
+        VIR_DEBUG("Peer is empty");
+
     familyStr = virXMLPropString(node, "family");
     if (familyStr && STREQ(familyStr, "ipv4"))
         family = AF_INET;
@@ -5756,6 +5759,14 @@ virDomainNetIpParseXML(xmlNodePtr node)
                        address);
         goto cleanup;
     }
+
+    if ((peer != NULL) && (virSocketAddrParse(&ip->peer, peer, family) < 0)) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("Failed to parse IP address: '%s'"),
+                           peer);
+            goto cleanup;
+    }
+
     ip->prefix = prefixValue;
 
     ret = ip;
@@ -5765,6 +5776,7 @@ virDomainNetIpParseXML(xmlNodePtr node)
     VIR_FREE(prefixStr);
     VIR_FREE(familyStr);
     VIR_FREE(address);
+    VIR_FREE(peer);
     VIR_FREE(ip);
     return ret;
 }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 85c4f554a2e2..0feff47ac99e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -513,6 +513,7 @@ typedef struct _virDomainNetIpDef virDomainNetIpDef;
 typedef virDomainNetIpDef *virDomainNetIpDefPtr;
 struct _virDomainNetIpDef {
     virSocketAddr address;       /* ipv4 or ipv6 address */
+    virSocketAddr peer;    /* ipv4 or ipv6 address of peer */
     unsigned int prefix; /* number of 1 bits in the net mask */
 };
 
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 4fb2e2a75b9d..1a0cf7fdcdd2 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -1456,7 +1456,7 @@ virNetworkIPDefParseXML(const char *networkName,
      */
 
     xmlNodePtr cur, save;
-    char *address = NULL, *netmask = NULL;
+    char *address = NULL, *netmask = NULL, *peer = NULL;
     unsigned long prefix = 0;
     int prefixRc;
     int result = -1;
@@ -1502,6 +1502,14 @@ virNetworkIPDefParseXML(const char *networkName,
     else
         def->prefix = prefix;
 
+    peer = virXPathString("string(./@peer)", ctxt);
+    if (peer && (virSocketAddrParse(&def->peer, peer, AF_UNSPEC) < 0)) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("Invalid peer '%s' in network '%s'"),
+                       peer, networkName);
+        goto cleanup;
+    }
+
     /* validate address, etc. for each family */
     if ((def->family == NULL) || (STREQ(def->family, "ipv4"))) {
         if (!(VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET) ||
@@ -1531,6 +1539,14 @@ virNetworkIPDefParseXML(const char *networkName,
                            prefix, networkName);
             goto cleanup;
         }
+        if (peer) {
+            if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->peer, AF_INET)) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("Family 'ipv4' specified for non-IPv4 address '%s' in network '%s'"),
+                               peer, networkName);
+                goto cleanup;
+            }
+        }
     } else if (STREQ(def->family, "ipv6")) {
         if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET6)) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -1550,6 +1566,14 @@ virNetworkIPDefParseXML(const char *networkName,
                            prefix, networkName);
             goto cleanup;
         }
+        if (peer) {
+            if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->peer, AF_INET6)) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("Family 'ipv6' specified for non-IPv6 address '%s' in network '%s'"),
+                               peer, networkName);
+                goto cleanup;
+            }
+        }
     } else {
         virReportError(VIR_ERR_XML_ERROR,
                        _("Unrecognized family '%s' in network '%s'"),
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index b72257b970a8..9b8e807fda3c 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -152,6 +152,7 @@ struct _virNetworkIpDef {
      */
     unsigned int prefix;        /* ipv6 - only prefix allowed */
     virSocketAddr netmask;      /* ipv4 - either netmask or prefix specified */
+    virSocketAddr peer;         /* ipv4 or ipv6 peer address */
 
     size_t nranges;             /* Zero or more dhcp ranges */
     virSocketAddrRangePtr ranges;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 348bbfbc01fc..a909b660b3ae 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -520,7 +520,7 @@ static int lxcContainerRenameAndEnableInterfaces(virDomainDefPtr vmDef,
 
             VIR_DEBUG("Adding IP address '%s/%u' to '%s'",
                       ipStr, ip->prefix, newname);
-            if (virNetDevSetIPAddress(newname, &ip->address, prefix) < 0) {
+            if (virNetDevSetIPAddress(newname, &ip->address, NULL, prefix) < 0) {
                 virReportError(VIR_ERR_SYSTEM_ERROR,
                                _("Failed to set IP address '%s' on %s"),
                                ipStr, newname);
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index a09a7e474fc5..b3dbea13b58f 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1970,7 +1970,7 @@ networkAddAddrToBridge(virNetworkObjPtr network,
     }
 
     if (virNetDevSetIPAddress(network->def->bridge,
-                              &ipdef->address, prefix) < 0)
+                              &ipdef->address, NULL, prefix) < 0)
         return -1;
 
     return 0;
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index aed50f546263..d171f34e6058 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -1039,21 +1039,28 @@ virNetDevCreateNetlinkAddressMessage(int messageType,
                                      const char *ifname,
                                      virSocketAddr *addr,
                                      unsigned int prefix,
-                                     virSocketAddr *broadcast)
+                                     virSocketAddr *broadcast,
+                                     virSocketAddr *peer)
 {
     struct nl_msg *nlmsg = NULL;
     struct ifaddrmsg ifa;
     unsigned int ifindex;
     void *addrData = NULL;
+    void *peerData = NULL;
     void *broadcastData = NULL;
     size_t addrDataLen;
 
     if (virNetDevGetIPAddressBinary(addr, &addrData, &addrDataLen) < 0)
         return NULL;
 
-    if (broadcast && virNetDevGetIPAddressBinary(broadcast, &broadcastData,
-                                                 &addrDataLen) < 0)
-        return NULL;
+    if (peer && VIR_SOCKET_ADDR_VALID(peer)) {
+        if (virNetDevGetIPAddressBinary(peer, &peerData, &addrDataLen) < 0)
+            return NULL;
+    } else if (broadcast) {
+        if (virNetDevGetIPAddressBinary(broadcast, &broadcastData,
+                                        &addrDataLen) < 0)
+            return NULL;
+    }
 
     /* Get the interface index */
     if ((ifindex = if_nametoindex(ifname)) == 0)
@@ -1078,12 +1085,15 @@ virNetDevCreateNetlinkAddressMessage(int messageType,
     if (nla_put(nlmsg, IFA_LOCAL, addrDataLen, addrData) < 0)
         goto buffer_too_small;
 
-    if (nla_put(nlmsg, IFA_ADDRESS, addrDataLen, addrData) < 0)
-        goto buffer_too_small;
+    if (peerData) {
+        if (nla_put(nlmsg, IFA_ADDRESS, addrDataLen, peerData) < 0)
+            goto buffer_too_small;
+    }
 
-    if (broadcastData &&
-        nla_put(nlmsg, IFA_BROADCAST, addrDataLen, broadcastData) < 0)
-        goto buffer_too_small;
+    if (broadcastData) {
+        if (nla_put(nlmsg, IFA_BROADCAST, addrDataLen, broadcastData) < 0)
+            goto buffer_too_small;
+    }
 
     return nlmsg;
 
@@ -1098,6 +1108,7 @@ virNetDevCreateNetlinkAddressMessage(int messageType,
  * virNetDevSetIPAddress:
  * @ifname: the interface name
  * @addr: the IP address (IPv4 or IPv6)
+ * @peer: The IP address of peer (IPv4 or IPv6)
  * @prefix: number of 1 bits in the netmask
  *
  * Add an IP address to an interface. This function *does not* remove
@@ -1108,6 +1119,7 @@ virNetDevCreateNetlinkAddressMessage(int messageType,
  */
 int virNetDevSetIPAddress(const char *ifname,
                           virSocketAddr *addr,
+                          virSocketAddr *peer,
                           unsigned int prefix)
 {
     virSocketAddr *broadcast = NULL;
@@ -1116,9 +1128,8 @@ int virNetDevSetIPAddress(const char *ifname,
     struct nlmsghdr *resp = NULL;
     unsigned int recvbuflen;
 
-
     /* The caller needs to provide a correct address */
-    if (VIR_SOCKET_ADDR_FAMILY(addr) == AF_INET) {
+    if (VIR_SOCKET_ADDR_FAMILY(addr) == AF_INET && !VIR_SOCKET_ADDR_VALID(peer)) {
         /* compute a broadcast address if this is IPv4 */
         if (VIR_ALLOC(broadcast) < 0)
             return -1;
@@ -1129,7 +1140,7 @@ int virNetDevSetIPAddress(const char *ifname,
 
     if (!(nlmsg = virNetDevCreateNetlinkAddressMessage(RTM_NEWADDR, ifname,
                                                        addr, prefix,
-                                                       broadcast)))
+                                                       broadcast, peer)))
         goto cleanup;
 
     if (virNetlinkCommand(nlmsg, &resp, &recvbuflen, 0, 0,
@@ -1288,7 +1299,7 @@ int virNetDevClearIPAddress(const char *ifname,
 
     if (!(nlmsg = virNetDevCreateNetlinkAddressMessage(RTM_DELADDR, ifname,
                                                        addr, prefix,
-                                                       NULL)))
+                                                       NULL, NULL)))
         goto cleanup;
 
     if (virNetlinkCommand(nlmsg, &resp, &recvbuflen, 0, 0,
@@ -1423,10 +1434,11 @@ virNetDevWaitDadFinish(virSocketAddrPtr *addrs, size_t count)
 
 int virNetDevSetIPAddress(const char *ifname,
                           virSocketAddr *addr,
+                          virSocketAddr *peer,
                           unsigned int prefix)
 {
     virCommandPtr cmd = NULL;
-    char *addrstr = NULL, *bcaststr = NULL;
+    char *addrstr = NULL, *bcaststr = NULL, *peerstr = NULL;
     virSocketAddr broadcast;
     int ret = -1;
 
@@ -1453,6 +1465,8 @@ int virNetDevSetIPAddress(const char *ifname,
     cmd = virCommandNew(IP_PATH);
     virCommandAddArgList(cmd, "addr", "add", NULL);
     virCommandAddArgFormat(cmd, "%s/%u", addrstr, prefix);
+    if (peerstr)
+        virCommandAddArgList(cmd, "peer", peerstr, NULL);
     if (bcaststr)
         virCommandAddArgList(cmd, "broadcast", bcaststr, NULL);
     virCommandAddArgList(cmd, "dev", ifname, NULL);
@@ -1465,6 +1479,7 @@ int virNetDevSetIPAddress(const char *ifname,
  cleanup:
     VIR_FREE(addrstr);
     VIR_FREE(bcaststr);
+    VIR_FREE(peerstr);
     virCommandFree(cmd);
     return ret;
 }
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
index e7719d58a410..240fff774d30 100644
--- a/src/util/virnetdev.h
+++ b/src/util/virnetdev.h
@@ -90,6 +90,7 @@ int virNetDevGetOnline(const char *ifname,
 
 int virNetDevSetIPAddress(const char *ifname,
                           virSocketAddr *addr,
+                          virSocketAddr *peer,
                           unsigned int prefix)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
 int virNetDevAddRoute(const char *ifname,
-- 
2.7.3




More information about the libvir-list mailing list