提交 3d4c1d94 编写于 作者: L Laine Stump 提交者: Daniel Veillard

Support for IPv6 / multiple addresses per interfaces

This patch updates the xml parsing and formatting, and the associated
virInterfaceDef data structure to support IPv6, along the way adding
support for multiple protocols per interface, and multiple IP
addresses per protocol.
* src/conf/interface_conf.[ch]: update the structures, code for parsing
  and serialization
上级 753c6c9c
...@@ -53,9 +53,31 @@ void virInterfaceBareDefFree(virInterfaceBareDefPtr def) { ...@@ -53,9 +53,31 @@ void virInterfaceBareDefFree(virInterfaceBareDefPtr def) {
VIR_FREE(def); VIR_FREE(def);
} }
static
void virInterfaceIpDefFree(virInterfaceIpDefPtr def) {
if (def == NULL)
return;
VIR_FREE(def->address);
}
static
void virInterfaceProtocolDefFree(virInterfaceProtocolDefPtr def) {
int ii;
if (def == NULL)
return;
for (ii = 0; ii < def->nips; ii++) {
virInterfaceIpDefFree(def->ips[ii]);
}
VIR_FREE(def->ips);
VIR_FREE(def->family);
VIR_FREE(def->gateway);
VIR_FREE(def);
}
void virInterfaceDefFree(virInterfaceDefPtr def) void virInterfaceDefFree(virInterfaceDefPtr def)
{ {
int i; int i, pp;
if (def == NULL) if (def == NULL)
return; return;
...@@ -89,10 +111,11 @@ void virInterfaceDefFree(virInterfaceDefPtr def) ...@@ -89,10 +111,11 @@ void virInterfaceDefFree(virInterfaceDefPtr def)
break; break;
} }
VIR_FREE(def->proto.family); /* free all protos */
VIR_FREE(def->proto.address); for (pp = 0; pp < def->nprotos; pp++) {
VIR_FREE(def->proto.gateway); virInterfaceProtocolDefFree(def->protos[pp]);
}
VIR_FREE(def->protos);
VIR_FREE(def); VIR_FREE(def);
} }
...@@ -222,22 +245,22 @@ virInterfaceDefParseBondArpValid(virConnectPtr conn, xmlXPathContextPtr ctxt) { ...@@ -222,22 +245,22 @@ virInterfaceDefParseBondArpValid(virConnectPtr conn, xmlXPathContextPtr ctxt) {
} }
static int static int
virInterfaceDefParseDhcp(virConnectPtr conn, virInterfaceDefPtr def, virInterfaceDefParseDhcp(virConnectPtr conn, virInterfaceProtocolDefPtr def,
xmlNodePtr dhcp, xmlXPathContextPtr ctxt) { xmlNodePtr dhcp, xmlXPathContextPtr ctxt) {
xmlNodePtr save; xmlNodePtr save;
char *tmp; char *tmp;
int ret = 0; int ret = 0;
def->proto.dhcp = 1; def->dhcp = 1;
save = ctxt->node; save = ctxt->node;
ctxt->node = dhcp; ctxt->node = dhcp;
/* Not much to do in the current version */ /* Not much to do in the current version */
tmp = virXPathString(conn, "string(./@peerdns)", ctxt); tmp = virXPathString(conn, "string(./@peerdns)", ctxt);
if (tmp) { if (tmp) {
if (STREQ(tmp, "yes")) if (STREQ(tmp, "yes"))
def->proto.peerdns = 1; def->peerdns = 1;
else if (STREQ(tmp, "no")) else if (STREQ(tmp, "no"))
def->proto.peerdns = 0; def->peerdns = 0;
else { else {
virInterfaceReportError(conn, VIR_ERR_XML_ERROR, virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
_("unknown dhcp peerdns value %s"), tmp); _("unknown dhcp peerdns value %s"), tmp);
...@@ -245,86 +268,208 @@ virInterfaceDefParseDhcp(virConnectPtr conn, virInterfaceDefPtr def, ...@@ -245,86 +268,208 @@ virInterfaceDefParseDhcp(virConnectPtr conn, virInterfaceDefPtr def,
} }
VIR_FREE(tmp); VIR_FREE(tmp);
} else } else
def->proto.peerdns = -1; def->peerdns = -1;
ctxt->node = save; ctxt->node = save;
return(ret); return(ret);
} }
static int static int
virInterfaceDefParseIp(virConnectPtr conn, virInterfaceDefPtr def, virInterfaceDefParseIp(virConnectPtr conn, virInterfaceIpDefPtr def,
xmlNodePtr ip ATTRIBUTE_UNUSED, xmlXPathContextPtr ctxt) { xmlXPathContextPtr ctxt) {
int ret = 0; int ret = 0;
char *tmp; char *tmp;
long l; long l;
tmp = virXPathString(conn, "string(./ip[1]/@address)", ctxt); tmp = virXPathString(conn, "string(./@address)", ctxt);
def->proto.address = tmp; def->address = tmp;
if (tmp != NULL) { if (tmp != NULL) {
ret = virXPathLong(conn, "string(./ip[1]/@prefix)", ctxt, &l); ret = virXPathLong(conn, "string(./@prefix)", ctxt, &l);
if (ret == 0) if (ret == 0)
def->proto.prefix = (int) l; def->prefix = (int) l;
else if (ret == -2) { else if (ret == -2) {
virInterfaceReportError(conn, VIR_ERR_XML_ERROR, virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
"%s", _("Invalid ip address prefix value")); "%s", _("Invalid ip address prefix value"));
return(-1); return(-1);
} }
} }
tmp = virXPathString(conn, "string(./route[1]/@gateway)", ctxt);
def->proto.gateway = tmp;
return(0); return(0);
} }
static int static int
virInterfaceDefParseProtoIPv4(virConnectPtr conn, virInterfaceDefPtr def, virInterfaceDefParseProtoIPv4(virConnectPtr conn, virInterfaceProtocolDefPtr def,
xmlXPathContextPtr ctxt) { xmlXPathContextPtr ctxt) {
xmlNodePtr dhcp, ip; xmlNodePtr dhcp;
int ret = 0; xmlNodePtr *ipNodes = NULL;
int nIpNodes, ii, ret = -1;
char *tmp;
tmp = virXPathString(conn, "string(./route[1]/@gateway)", ctxt);
def->gateway = tmp;
dhcp = virXPathNode(conn, "./dhcp", ctxt); dhcp = virXPathNode(conn, "./dhcp", ctxt);
if (dhcp != NULL) if (dhcp != NULL)
ret = virInterfaceDefParseDhcp(conn, def, dhcp, ctxt); ret = virInterfaceDefParseDhcp(conn, def, dhcp, ctxt);
if (ret != 0)
return(ret);
nIpNodes = virXPathNodeSet(conn, "./ip", ctxt, &ipNodes);
if (ipNodes == NULL)
return 0;
if (VIR_ALLOC_N(def->ips, nIpNodes) < 0) {
virReportOOMError(conn);
goto error;
}
def->nips = 0;
for (ii = 0; ii < nIpNodes; ii++) {
virInterfaceIpDefPtr ip;
if (VIR_ALLOC(ip) < 0) {
virReportOOMError(conn);
goto error;
}
ctxt->node = ipNodes[ii];
ret = virInterfaceDefParseIp(conn, ip, ctxt);
if (ret != 0) {
virInterfaceIpDefFree(ip);
goto error;
}
def->ips[def->nips++] = ip;
}
ret = 0;
error:
VIR_FREE(ipNodes);
return(ret);
}
static int
virInterfaceDefParseProtoIPv6(virConnectPtr conn, virInterfaceProtocolDefPtr def,
xmlXPathContextPtr ctxt) {
xmlNodePtr dhcp, autoconf;
xmlNodePtr *ipNodes = NULL;
int nIpNodes, ii, ret = -1;
char *tmp;
tmp = virXPathString(conn, "string(./route[1]/@gateway)", ctxt);
def->gateway = tmp;
autoconf = virXPathNode(conn, "./autoconf", ctxt);
if (autoconf != NULL)
def->autoconf = 1;
dhcp = virXPathNode(conn, "./dhcp", ctxt);
if (dhcp != NULL)
ret = virInterfaceDefParseDhcp(conn, def, dhcp, ctxt);
if (ret != 0) if (ret != 0)
return(ret); return(ret);
ip = virXPathNode(conn, "./ip", ctxt); nIpNodes = virXPathNodeSet(conn, "./ip", ctxt, &ipNodes);
if (ip != NULL) if (ipNodes == NULL)
ret = virInterfaceDefParseIp(conn, def, ip, ctxt); return 0;
if (VIR_ALLOC_N(def->ips, nIpNodes) < 0) {
virReportOOMError(conn);
goto error;
}
def->nips = 0;
for (ii = 0; ii < nIpNodes; ii++) {
virInterfaceIpDefPtr ip;
if (VIR_ALLOC(ip) < 0) {
virReportOOMError(conn);
goto error;
}
ctxt->node = ipNodes[ii];
ret = virInterfaceDefParseIp(conn, ip, ctxt);
if (ret != 0) {
virInterfaceIpDefFree(ip);
goto error;
}
def->ips[def->nips++] = ip;
}
ret = 0;
error:
VIR_FREE(ipNodes);
return(ret); return(ret);
} }
static int static int
virInterfaceDefParseIfAdressing(virConnectPtr conn, virInterfaceDefPtr def, virInterfaceDefParseIfAdressing(virConnectPtr conn, virInterfaceDefPtr def,
xmlXPathContextPtr ctxt) { xmlXPathContextPtr ctxt) {
xmlNodePtr cur, save; xmlNodePtr save;
int ret; xmlNodePtr *protoNodes = NULL;
int nProtoNodes, pp, ret = -1;
char *tmp; char *tmp;
cur = virXPathNode(conn, "./protocol[1]", ctxt);
if (cur == NULL)
return(0);
save = ctxt->node; save = ctxt->node;
ctxt->node = cur;
tmp = virXPathString(conn, "string(./@family)", ctxt); nProtoNodes = virXPathNodeSet(conn, "./protocol", ctxt, &protoNodes);
if (tmp == NULL) { if (nProtoNodes <= 0) {
virInterfaceReportError(conn, VIR_ERR_XML_ERROR, /* no protocols is an acceptable outcome */
"%s", _("protocol misses the family attribute")); return 0;
ret = -1;
goto done;
} }
if (STREQ(tmp, "ipv4")) {
def->proto.family = tmp; if (VIR_ALLOC_N(def->protos, nProtoNodes) < 0) {
ret = virInterfaceDefParseProtoIPv4(conn, def, ctxt); virReportOOMError(conn);
} else { goto error;
virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
_("unsupported protocol family '%s'"), tmp);
ret = -1;
VIR_FREE(tmp);
} }
done: def->nprotos = 0;
for (pp = 0; pp < nProtoNodes; pp++) {
virInterfaceProtocolDefPtr proto;
if (VIR_ALLOC(proto) < 0) {
virReportOOMError(conn);
goto error;
}
ctxt->node = protoNodes[pp];
tmp = virXPathString(conn, "string(./@family)", ctxt);
if (tmp == NULL) {
virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
"%s", _("protocol misses the family attribute"));
virInterfaceProtocolDefFree(proto);
goto error;
}
proto->family = tmp;
if (STREQ(tmp, "ipv4")) {
ret = virInterfaceDefParseProtoIPv4(conn, proto, ctxt);
if (ret != 0) {
virInterfaceProtocolDefFree(proto);
goto error;
}
} else if (STREQ(tmp, "ipv6")) {
ret = virInterfaceDefParseProtoIPv6(conn, proto, ctxt);
if (ret != 0) {
virInterfaceProtocolDefFree(proto);
goto error;
}
} else {
virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
_("unsupported protocol family '%s'"), tmp);
virInterfaceProtocolDefFree(proto);
goto error;
}
def->protos[def->nprotos++] = proto;
}
ret = 0;
error:
VIR_FREE(protoNodes);
ctxt->node = save; ctxt->node = save;
return(ret); return(ret);
...@@ -999,30 +1144,44 @@ virInterfaceVlanDefFormat(virConnectPtr conn, virBufferPtr buf, ...@@ -999,30 +1144,44 @@ virInterfaceVlanDefFormat(virConnectPtr conn, virBufferPtr buf,
static int static int
virInterfaceProtocolDefFormat(virConnectPtr conn ATTRIBUTE_UNUSED, virInterfaceProtocolDefFormat(virConnectPtr conn ATTRIBUTE_UNUSED,
virBufferPtr buf, const virInterfaceDefPtr def) { virBufferPtr buf, const virInterfaceDefPtr def) {
if (def->proto.family == NULL) int pp, ii;
return(0);
virBufferVSprintf(buf, " <protocol family='%s'>\n", def->proto.family); for (pp = 0; pp < def->nprotos; pp++) {
if (def->proto.dhcp) {
if (def->proto.peerdns == 0) virBufferVSprintf(buf, " <protocol family='%s'>\n", def->protos[pp]->family);
virBufferAddLit(buf, " <dhcp peerdns='no'/>\n");
else if (def->proto.peerdns == 1) if (def->protos[pp]->autoconf) {
virBufferAddLit(buf, " <dhcp peerdns='yes'/>\n"); virBufferAddLit(buf, " <autoconf/>\n");
else }
virBufferAddLit(buf, " <dhcp/>\n");
} if (def->protos[pp]->dhcp) {
if (def->proto.address != NULL) { if (def->protos[pp]->peerdns == 0)
if (def->proto.prefix != 0) virBufferAddLit(buf, " <dhcp peerdns='no'/>\n");
virBufferVSprintf(buf, " <ip address='%s' prefix='%d'/>\n", else if (def->protos[pp]->peerdns == 1)
def->proto.address, def->proto.prefix); virBufferAddLit(buf, " <dhcp peerdns='yes'/>\n");
else else
virBufferVSprintf(buf, " <ip address='%s'/>\n", virBufferAddLit(buf, " <dhcp/>\n");
def->proto.address); }
}
if (def->proto.gateway != NULL) { for (ii = 0; ii < def->protos[pp]->nips; ii++) {
virBufferVSprintf(buf, " <route gateway='%s'/>\n", if (def->protos[pp]->ips[ii]->address != NULL) {
def->proto.gateway);
virBufferVSprintf(buf, " <ip address='%s'",
def->protos[pp]->ips[ii]->address);
if (def->protos[pp]->ips[ii]->prefix != 0) {
virBufferVSprintf(buf, " prefix='%d'",
def->protos[pp]->ips[ii]->prefix);
}
virBufferAddLit(buf, "/>\n");
}
}
if (def->protos[pp]->gateway != NULL) {
virBufferVSprintf(buf, " <route gateway='%s'/>\n",
def->protos[pp]->gateway);
}
virBufferAddLit(buf, " </protocol>\n");
} }
virBufferAddLit(buf, " </protocol>\n");
return(0); return(0);
} }
......
...@@ -124,14 +124,23 @@ struct _virInterfaceVlanDef { ...@@ -124,14 +124,23 @@ struct _virInterfaceVlanDef {
char *devname; /* device name for vlan */ char *devname; /* device name for vlan */
}; };
typedef struct _virInterfaceIpDef virInterfaceIpDef;
typedef virInterfaceIpDef *virInterfaceIpDefPtr;
struct _virInterfaceIpDef {
char *address; /* ip address */
int prefix; /* ip prefix */
};
typedef struct _virInterfaceProtocolDef virInterfaceProtocolDef; typedef struct _virInterfaceProtocolDef virInterfaceProtocolDef;
typedef virInterfaceProtocolDef *virInterfaceProtocolDefPtr; typedef virInterfaceProtocolDef *virInterfaceProtocolDefPtr;
struct _virInterfaceProtocolDef { struct _virInterfaceProtocolDef {
char *family; /* ipv4 only right now */ char *family; /* ipv4 or ipv6 */
int dhcp; /* use dhcp */ int dhcp; /* use dhcp */
int peerdns; /* dhcp peerdns ? */ int peerdns; /* dhcp peerdns ? */
char *address; /* ip address */ int autoconf; /* only useful if family is ipv6 */
int prefix; /* ip prefix */ int nips;
virInterfaceIpDefPtr *ips; /* ptr to array of ips[nips] */
char *gateway; /* route gateway */ char *gateway; /* route gateway */
}; };
...@@ -152,8 +161,8 @@ struct _virInterfaceDef { ...@@ -152,8 +161,8 @@ struct _virInterfaceDef {
virInterfaceBondDef bond; virInterfaceBondDef bond;
} data; } data;
/* separated as we may allow multiple of those in the future */ int nprotos;
virInterfaceProtocolDef proto; virInterfaceProtocolDefPtr *protos; /* ptr to array of protos[nprotos] */
}; };
typedef struct _virInterfaceObj virInterfaceObj; typedef struct _virInterfaceObj virInterfaceObj;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册