confd: Create an enumerator for interface types

This has multiple advantages:

- Less chances of typos is repeated "infix-if-type:foo" strings
  scattered throughout the code

- We can lean on GCC's `-Werror=switch` to make sure that iface
  specific logic always handles all types (which was not always the
  case - see follow-up commits)

- We can potentially create a `struct afspec_ops` in the future, which
  could then be indexed by this enum
This commit is contained in:
Tobias Waldekranz
2025-02-11 20:36:27 +01:00
parent b1830a36d4
commit c22339c2cd
6 changed files with 118 additions and 82 deletions
+7 -8
View File
@@ -6,6 +6,7 @@
#include "core.h"
#include "cni.h"
#include "ietf-interfaces.h"
#define CNI_NAME "/etc/cni/net.d/%s.conflist"
@@ -86,13 +87,13 @@ FILE *cni_popen(const char *fmt, const char *ifname)
return popenf("re", "nsenter -t %d -n %s", pid, cmd);
}
static bool iface_is_cni(const char *ifname, struct lyd_node *node, const char **type)
static bool iface_is_cni(const char *ifname, struct lyd_node *node, enum iftype *type)
{
struct lyd_node *net = lydx_get_child(node, "container-network");
if (net) {
if (type)
*type = lydx_get_cattr(net, "type");
*type = iftype_from_iface(net);
return true;
}
@@ -365,9 +366,7 @@ static int iface_gen_cni(const char *ifname, struct lyd_node *cif)
* "container-network": {}, so someone does their job.
*/
if (!type) {
const char *iftype = lydx_get_cattr(cif, "type");
if (iftype && !strcmp(iftype, "infix-if-type:bridge"))
if (iftype_from_iface(cif) == IFT_BRIDGE)
type = "infix-interfaces:bridge";
else
type = "infix-interfaces:host";
@@ -386,7 +385,7 @@ static int iface_gen_cni(const char *ifname, struct lyd_node *cif)
int cni_netdag_gen_iface(struct dagger *net, const char *ifname,
struct lyd_node *dif, struct lyd_node *cif)
{
const char *cni_type = NULL;
enum iftype cni_type;
FILE *fp;
if (iface_is_cni(ifname, cif, &cni_type)) {
@@ -403,7 +402,7 @@ int cni_netdag_gen_iface(struct dagger *net, const char *ifname,
err = iface_gen_cni(ifname, cif);
if (err)
return err;
if (cni_type && !strcmp(cni_type, "bridge"))
if (cni_type == IFT_BRIDGE)
return 1; /* CNI bridges are managed by podman */
} else if (iface_is_cni(ifname, dif, &cni_type)) {
/* No longer a container-network, clean up. */
@@ -414,7 +413,7 @@ int cni_netdag_gen_iface(struct dagger *net, const char *ifname,
fprintf(fp, "container -a -f delete network %s >/dev/null\n", ifname);
fclose(fp);
if (cni_type && !strcmp(cni_type, "bridge"))
if (cni_type == IFT_BRIDGE)
return 1; /* CNI bridges are managed by podman */
}
+1 -2
View File
@@ -104,7 +104,6 @@ out:
int netdag_gen_ethtool(struct dagger *net, struct lyd_node *cif, struct lyd_node *dif)
{
struct lyd_node *eth = lydx_get_child(dif, "ethernet");
const char *type = lydx_get_cattr(cif, "type");
int err;
/*
@@ -121,7 +120,7 @@ int netdag_gen_ethtool(struct dagger *net, struct lyd_node *cif, struct lyd_node
*
* Hence this "redundant" check.
*/
if (strcmp(type, "infix-if-type:ethernet"))
if (iftype_from_iface(cif) != IFT_ETH)
return 0;
if (!eth)
+63 -65
View File
@@ -383,58 +383,62 @@ static int netdag_gen_afspec_add(sr_session_ctx_t *session, struct dagger *net,
struct lyd_node *cif, FILE *ip)
{
const char *ifname = lydx_get_cattr(cif, "name");
const char *iftype = lydx_get_cattr(cif, "type");
int err = 0;
DEBUG_IFACE(dif, "");
if (!strcmp(iftype, "infix-if-type:bridge")) {
err = bridge_gen(dif, cif, ip, 1);
} else if (!strcmp(iftype, "infix-if-type:dummy")) {
err = netdag_gen_dummy(net, NULL, cif, ip);
} else if (!strcmp(iftype, "infix-if-type:veth")) {
err = netdag_gen_veth(net, NULL, cif, ip);
} else if (!strcmp(iftype, "infix-if-type:vlan")) {
err = netdag_gen_vlan(net, NULL, cif, ip);
} else if (!strcmp(iftype, "infix-if-type:ethernet")) {
sr_session_set_error_message(net->session, "Cannot create fixed Ethernet interface %s,"
" wrong type or name.", ifname);
return -ENOENT;
} else if (!strcmp(iftype, "infix-if-type:gre") || !strcmp(iftype, "infix-if-type:gretap")) {
err = gre_gen(net, NULL, cif, ip);
} else if (!strcmp(iftype, "infix-if-type:vxlan")) {
err = vxlan_gen(net, NULL, cif, ip);
} else {
sr_session_set_error_message(net->session, "%s: unsupported interface type \"%s\"", ifname, iftype);
switch (iftype_from_iface(cif)) {
case IFT_BRIDGE:
return bridge_gen(dif, cif, ip, 1);
case IFT_DUMMY:
return netdag_gen_dummy(net, NULL, cif, ip);
case IFT_GRE:
case IFT_GRETAP:
return gre_gen(net, NULL, cif, ip);
case IFT_VETH:
return netdag_gen_veth(net, NULL, cif, ip);
case IFT_VLAN:
return netdag_gen_vlan(net, NULL, cif, ip);
case IFT_VXLAN:
return vxlan_gen(net, NULL, cif, ip);
case IFT_ETH:
case IFT_ETHISH:
case IFT_UNKNOWN:
sr_session_set_error_message(net->session, "%s: unsupported interface type \"%s\"",
ifname, lydx_get_cattr(cif, "type"));
return -ENOSYS;
}
if (err)
return err;
return 0;
__builtin_unreachable();
return -EINVAL;
}
static int netdag_gen_afspec_set(sr_session_ctx_t *session, struct dagger *net, struct lyd_node *dif,
struct lyd_node *cif, FILE *ip)
{
const char *ifname = lydx_get_cattr(cif, "name");
const char *iftype = lydx_get_cattr(cif, "type");
DEBUG_IFACE(dif, "");
if (!strcmp(iftype, "infix-if-type:bridge"))
switch (iftype_from_iface(cif)) {
case IFT_BRIDGE:
return bridge_gen(dif, cif, ip, 0);
if (!strcmp(iftype, "infix-if-type:vlan"))
case IFT_VLAN:
return netdag_gen_vlan(net, dif, cif, ip);
if (!strcmp(iftype, "infix-if-type:veth"))
case IFT_GRETAP:
case IFT_VETH:
case IFT_VXLAN:
return 0;
if (!strcmp(iftype, "infix-if-type:gretap"))
return 0;
if (!strcmp(iftype, "infix-if-type:vxlan"))
return 0;
ERROR("%s: unsupported interface type \"%s\"", ifname, iftype);
return -ENOSYS;
case IFT_DUMMY:
case IFT_ETH:
case IFT_ETHISH:
case IFT_GRE:
case IFT_UNKNOWN:
return ERR_IFACE(cif, -ENOSYS, "unsupported interface type \"%s\"",
lydx_get_cattr(cif, "type"));
}
__builtin_unreachable();
return -EINVAL;
}
static bool is_phys_addr_deleted(struct lyd_node *dif)
@@ -449,33 +453,28 @@ static bool is_phys_addr_deleted(struct lyd_node *dif)
static bool netdag_must_del(struct lyd_node *dif, struct lyd_node *cif)
{
const char *iftype = lydx_get_cattr(cif, "type");
if (strcmp(iftype, "infix-if-type:ethernet") &&
strcmp(iftype, "infix-if-type:etherlike")) {
if (is_phys_addr_deleted(dif))
return true;
}
if (!strcmp(iftype, "infix-if-type:vlan")) {
if (lydx_get_descendant(lyd_child(dif), "vlan", NULL))
return true;
} else if (!strcmp(iftype, "infix-if-type:veth")) {
if (lydx_get_descendant(lyd_child(dif), "veth", NULL))
return true;
} else if (!strcmp(iftype, "infix-if-type:gre") || !strcmp(iftype, "infix-if-type:gretap")) {
if (lydx_get_descendant(lyd_child(dif), "gre", NULL))
return true;
} else if (!strcmp(iftype, "infix-if-type:vxlan")) {
if (lydx_get_descendant(lyd_child(dif), "vxlan", NULL))
return true;
/*
} else if (!strcmp(iftype, "infix-if-type:lag")) {
if (is_phys_addr_deleted(dif))
return true;
... REMEMBER WHEN ADDING BOND SUPPORT ...
*/
switch (iftype_from_iface(cif)) {
case IFT_BRIDGE:
case IFT_DUMMY:
break;
case IFT_ETH:
case IFT_ETHISH:
/* case IFT_LAG: */
/* ... REMEMBER WHEN ADDING BOND SUPPORT ... */
return is_phys_addr_deleted(dif);
case IFT_GRE:
case IFT_GRETAP:
return lydx_get_descendant(lyd_child(dif), "gre", NULL);
case IFT_VLAN:
return lydx_get_descendant(lyd_child(dif), "vlan", NULL);
case IFT_VETH:
return lydx_get_descendant(lyd_child(dif), "veth", NULL);
case IFT_VXLAN:
return lydx_get_descendant(lyd_child(dif), "vxlan", NULL);
case IFT_UNKNOWN:
ERR_IFACE(cif, -EINVAL, "unsupported interface type \"%s\"",
lydx_get_cattr(cif, "type"));
return true;
}
return false;
@@ -485,7 +484,6 @@ static int netdag_gen_iface_del(struct dagger *net, struct lyd_node *dif,
struct lyd_node *cif, bool fixed)
{
const char *ifname = lydx_get_cattr(dif, "name");
const char *iftype = lydx_get_cattr(dif, "type");
FILE *ip;
DEBUG_IFACE(dif, "");
@@ -493,7 +491,7 @@ static int netdag_gen_iface_del(struct dagger *net, struct lyd_node *dif,
if (dagger_should_skip_current(net, ifname))
return 0;
if (iftype && !strcmp(iftype, "infix-if-type:veth")) {
if (iftype_from_iface(cif) == IFT_VETH) {
struct lyd_node *node;
const char *peer;
+38
View File
@@ -21,6 +21,44 @@
#define ONOFF(boolean) boolean ? "on" : "off"
#define IFTYPES(_map) \
_map(IFT_BRIDGE, "infix-if-type:bridge") \
_map(IFT_DUMMY, "infix-if-type:dummy") \
_map(IFT_ETH, "infix-if-type:ethernet") \
_map(IFT_ETHISH, "infix-if-type:etherlike") \
_map(IFT_GRE, "infix-if-type:gre") \
_map(IFT_GRETAP, "infix-if-type:gretap") \
_map(IFT_VETH, "infix-if-type:veth") \
_map(IFT_VLAN, "infix-if-type:vlan") \
_map(IFT_VXLAN, "infix-if-type:vxlan") \
/* */
enum iftype {
#define ift_enum(_enum, _str) _enum,
IFTYPES(ift_enum)
#undef ift_enum
IFT_UNKNOWN
};
static inline enum iftype iftype_from_str(const char *typestr)
{
#define ift_cmp(_enum, _str) if (!strcmp(typestr, _str)) return _enum;
IFTYPES(ift_cmp)
#undef ift_cmp
return IFT_UNKNOWN;
}
static inline enum iftype iftype_from_iface(struct lyd_node *ifn)
{
const char *typestr = lydx_get_cattr(ifn, "type");
if (!typestr)
return IFT_UNKNOWN;
return iftype_from_str(typestr);
}
static inline const char *bridge_tagtype2str(const char *type)
{
if (!strcmp(type, "ieee802-dot1q-types:c-vlan"))
+1 -1
View File
@@ -97,7 +97,7 @@ int bridge_mcd_gen(struct lyd_node *cifs)
return -EIO;
LYX_LIST_FOR_EACH(cifs, cif, "interface") {
if (strcmp(lydx_get_cattr(cif, "type"), "infix-if-type:bridge"))
if (iftype_from_iface(cif) != IFT_BRIDGE)
continue;
err = gen_bridge(cif, conf);
+8 -6
View File
@@ -6,13 +6,12 @@
int gre_gen(struct dagger *net, struct lyd_node *dif,
struct lyd_node *cif, FILE *ip)
{
const char *ifname, *iftype, *local, *remote, *mac = NULL;
const char *ifname, *local, *remote, *mac = NULL;
struct lyd_node *node = NULL;
char gretype[10] = "";
int ipv6;
ifname = lydx_get_cattr(cif, "name");
iftype = lydx_get_cattr(cif, "type");
node = lydx_get_descendant(lyd_child(cif), "gre", NULL);
if (!node)
@@ -22,13 +21,16 @@ int gre_gen(struct dagger *net, struct lyd_node *dif,
remote = lydx_get_cattr(node, "remote");
ipv6 = !!strstr(local, ":");
if (!strcmp(iftype, "infix-if-type:gre")) {
switch (iftype_from_iface(cif)) {
case IFT_GRE:
snprintf(gretype, sizeof(gretype), "%sgre", ipv6 ? "ip6" : "");
}
else if (!strcmp(iftype, "infix-if-type:gretap")) {
break;
case IFT_GRETAP:
snprintf(gretype, sizeof(gretype), "%sgretap", ipv6 ? "ip6" : "");
mac = get_phys_addr(cif, NULL);
break;
default:
return -EINVAL;
}
fprintf(ip, "link add name %s type %s local %s remote %s", ifname, gretype, local, remote);