diff --git a/client/compat.c b/client/compat.c index 7df8ee6cf..37f92e767 100644 --- a/client/compat.c +++ b/client/compat.c @@ -773,6 +773,18 @@ __ni_compat_generate_team_runner(xml_node_t *tnode, const ni_team_runner_t *runn return TRUE; } +static ni_bool_t +ni_compat_generate_team_link_watch_policy(xml_node_t *tnode, const ni_team_link_watch_policy_t policy) +{ + const char *name; + + if (policy != NI_TEAM_LINK_WATCH_POLICY_ANY && + (name = ni_team_link_watch_policy_type_to_name(policy))) + xml_node_new_element("link_watch_policy", tnode, name); + + return TRUE; +} + static ni_bool_t __ni_compat_generate_team_link_watch(xml_node_t *tnode, const ni_team_link_watch_array_t *array) { @@ -823,6 +835,9 @@ __ni_compat_generate_team_link_watch(xml_node_t *tnode, const ni_team_link_watch xml_node_new_element("send_always", watch, ni_format_boolean(arp->send_always)); xml_node_new_element("missed_max", watch, ni_sprint_uint(arp->missed_max)); + + if (arp->vlanid != UINT16_MAX) + xml_node_new_element("vlanid", watch, ni_sprint_uint(arp->vlanid)); } break; @@ -904,6 +919,50 @@ __ni_compat_generate_team_ports(xml_node_t *tnode, const ni_team_port_array_t *a return TRUE; } +static ni_bool_t +ni_compat_generate_team_notify_peers(xml_node_t *parent, const ni_team_t *team) +{ + xml_node_t *node; + + if (!parent || !team) + return FALSE; + + if (team->notify_peers.count == -1U && team->notify_peers.interval == -1U) + return TRUE; + + node = xml_node_create(parent, "notify_peers"); + + if (team->notify_peers.count != -1U) + xml_node_new_element("count", node, ni_sprint_uint(team->notify_peers.count)); + + if (team->notify_peers.interval != -1U) + xml_node_new_element("interval", node, ni_sprint_uint(team->notify_peers.interval)); + + return TRUE; +} + +static ni_bool_t +ni_compat_generate_team_mcast_rejoin(xml_node_t *parent, const ni_team_t *team) +{ + xml_node_t *node; + + if (!parent || !team) + return FALSE; + + if (team->mcast_rejoin.count == -1U && team->mcast_rejoin.interval == -1U) + return TRUE; + + node = xml_node_create(parent, "mcast_rejoin"); + + if (team->mcast_rejoin.count != -1U) + xml_node_new_element("count", node, ni_sprint_uint(team->mcast_rejoin.count)); + + if (team->mcast_rejoin.interval != -1U) + xml_node_new_element("interval", node, ni_sprint_uint(team->mcast_rejoin.interval)); + + return TRUE; +} + static ni_bool_t __ni_compat_generate_team(xml_node_t *ifnode, const ni_compat_netdev_t *compat) { @@ -918,9 +977,20 @@ __ni_compat_generate_team(xml_node_t *ifnode, const ni_compat_netdev_t *compat) ni_link_address_print(&compat->dev->link.hwaddr)); } + if (team->debug_level > 0) + xml_node_new_element("debug_level", tnode, ni_sprint_uint(team->debug_level)); + + if (!ni_compat_generate_team_notify_peers(tnode, team)) + return FALSE; + if (!ni_compat_generate_team_mcast_rejoin(tnode, team)) + return FALSE; + if (!__ni_compat_generate_team_runner(tnode, &team->runner)) return FALSE; + if (!ni_compat_generate_team_link_watch_policy(tnode, team->link_watch_policy)) + return FALSE; + if (!__ni_compat_generate_team_link_watch(tnode, &team->link_watch)) return FALSE; diff --git a/client/suse/compat-suse.c b/client/suse/compat-suse.c index fb4349f19..85b01df12 100644 --- a/client/suse/compat-suse.c +++ b/client/suse/compat-suse.c @@ -2473,6 +2473,22 @@ try_add_team_link_watch(const ni_sysconfig_t *sc, ni_netdev_t *dev, const char * goto failure; } } + + if ((var = __find_indexed_variable(sc, "TEAM_LW_ARP_PING_VLANID", suffix))) { + uint32_t u32; + + if (ni_parse_uint(var->value, &u32, 0) < 0) { + ni_error("ifcfg-%s: Cannot parse TEAM_LW_ARP_PING_VLANID%s='%s'", + dev->name, suffix, var->value); + goto failure; + } + if (u32 > 4096) { + ni_error("ifcfg-%s: Invalid value in TEAM_LW_ARP_PING_VLANID%s='%s'", + dev->name, suffix, var->value); + goto failure; + } + arp->vlanid = (uint16_t)u32; + } } break; @@ -2798,6 +2814,54 @@ try_team(ni_sysconfig_t *sc, ni_compat_netdev_t *compat) } } + if ((value = ni_sysconfig_get_value(sc, "TEAM_DEBUG_LEVEL")) != NULL) { + if (ni_parse_uint(value, &team->debug_level, 0) < 0) { + ni_error("ifcfg-%s: Cannot parse TEAM_DEBUG_LEVEL='%s'", + dev->name, value); + return -1; + } + } + + if ((value = ni_sysconfig_get_value(sc, "TEAM_NOTIFY_PEERS_COUNT")) != NULL) { + if (ni_parse_uint(value, &team->notify_peers.count, 0) < 0) { + ni_error("ifcfg-%s: Cannot parse TEAM_NOTIFY_PEERS_COUNT='%s'", + dev->name, value); + return -1; + } + } + + if ((value = ni_sysconfig_get_value(sc, "TEAM_NOTIFY_PEERS_INTERVAL")) != NULL) { + if (ni_parse_uint(value, &team->notify_peers.interval, 0) < 0) { + ni_error("ifcfg-%s: Cannot parse TEAM_NOTIFY_PEERS_INTERVAL='%s'", + dev->name, value); + return -1; + } + } + + if ((value = ni_sysconfig_get_value(sc, "TEAM_MCAST_REJOIN_COUNT")) != NULL) { + if (ni_parse_uint(value, &team->mcast_rejoin.count, 0) < 0) { + ni_error("ifcfg-%s: Cannot parse TEAM_MCAST_REJOIN_COUNT='%s'", + dev->name, value); + return -1; + } + } + + if ((value = ni_sysconfig_get_value(sc, "TEAM_MCAST_REJOIN_INTERVAL")) != NULL) { + if (ni_parse_uint(value, &team->mcast_rejoin.interval, 0) < 0) { + ni_error("ifcfg-%s: Cannot parse TEAM_MCAST_REJOIN_INTERVAL='%s'", + dev->name, value); + return -1; + } + } + + if ((value = ni_sysconfig_get_value(sc, "TEAM_LINK_WATCH_POLICY"))) { + if (!ni_team_link_watch_policy_name_to_type(value, &team->link_watch_policy)) { + ni_error("ifcfg-%s: Cannot parse TEAM_LINK_WATCH_POLICY='%s'", + dev->name, value); + return -1; + } + } + if (__process_indexed_variables(sc, dev, "TEAM_LW_NAME", try_add_team_link_watch) < 0) return -1; diff --git a/include/wicked/team.h b/include/wicked/team.h index da387e453..94e93dced 100644 --- a/include/wicked/team.h +++ b/include/wicked/team.h @@ -158,6 +158,7 @@ typedef struct ni_team_link_watch_arp { ni_bool_t validate_inactive; ni_bool_t send_always; unsigned int missed_max; + uint16_t vlanid; } ni_team_link_watch_arp_t; typedef struct ni_team_link_watch_tipc { @@ -227,11 +228,29 @@ typedef struct ni_team_port_array { ni_team_port_t ** data; } ni_team_port_array_t; +typedef enum { + NI_TEAM_LINK_WATCH_POLICY_ANY = 0U, + NI_TEAM_LINK_WATCH_POLICY_ALL = 1, +} ni_team_link_watch_policy_t; + +typedef struct ni_team_notify_peers { + unsigned int count; + unsigned int interval; +} ni_team_notify_peers_t; + +typedef struct ni_team_mcast_rejoin { + unsigned int count; + unsigned int interval; +} ni_team_mcast_rejoin_t; /* * team device */ struct ni_team { + unsigned int debug_level; + ni_team_notify_peers_t notify_peers; + ni_team_mcast_rejoin_t mcast_rejoin; ni_team_runner_t runner; + ni_team_link_watch_policy_t link_watch_policy; ni_team_link_watch_array_t link_watch; ni_team_port_array_t ports; }; @@ -261,6 +280,10 @@ extern ni_bool_t ni_team_ab_hwaddr_policy_name_to_type(const char *, ni_team_ extern const char * ni_team_link_watch_type_to_name(ni_team_link_watch_type_t); extern ni_bool_t ni_team_link_watch_name_to_type(const char *, ni_team_link_watch_type_t *); +extern const char * ni_team_link_watch_policy_type_to_name(ni_team_link_watch_policy_t); +extern ni_bool_t ni_team_link_watch_policy_name_to_type(const char *, + ni_team_link_watch_policy_t *); + extern ni_team_link_watch_t * ni_team_link_watch_new(ni_team_link_watch_type_t); extern void ni_team_link_watch_free(ni_team_link_watch_t *); extern ni_declare_ptr_array_append(ni_team_link_watch); diff --git a/man/ifcfg-team.5.in b/man/ifcfg-team.5.in index 28d431d07..9b2b860f0 100644 --- a/man/ifcfg-team.5.in +++ b/man/ifcfg-team.5.in @@ -1,420 +1,440 @@ -.\" Process this file with -.\" groff -man -Tascii foo.1 +.\" Automatically generated by Pandoc 2.18 .\" -.TH IFCFG-TEAM 5 "August 2015" "wicked" "Network configuration" -.\" ... - +.\" Define V font for inline verbatim, using C font in formats +.\" that render this, and otherwise B font. +.ie "\f[CB]x\f[]"x" \{\ +. ftr V B +. ftr VI BI +. ftr VB B +. ftr VBI BI +.\} +.el \{\ +. ftr V CR +. ftr VI CI +. ftr VB CB +. ftr VBI CBI +.\} +.TH "IFCFG-TEAM" "5" "January 29, 2024" "Wicked User Manual" "" +.hy .SH NAME -ifcfg-team \- interface team configuration +.PP +ifcfg-team - interface team configuration .SH SYNOPSIS -.B /etc/sysconfig/network/ifcfg-* - - +.PP +\f[V]/etc/sysconfig/network/ifcfg-*\f[R] .SH Team Interfaces -To setup a team interface you need a configuration file ifcfg-team with -the usual network settings. But you must add additional variables +.PP +To setup a team interface you need a configuration file ifcfg-team +with the usual network settings. +But you must add additional variables .TP -.BR TEAM_RUNNER -must be set to one of the following types to identify this interface as a team interface: -.RS 7 +\f[V]TEAM_DEBUG_LEVEL\f[R] +Level of debug messages. +The higher it is the more debug messages will be printed. +.RS .PP -.BR "broadcast "\(em -Team device transmits packets via all its ports. +Default: \f[B]0\f[R] (disabled) +.RE +.TP +\f[V]TEAM_NOTIFY_PEERS_COUNT\f[R] +Number of bursts of unsolicited NAs and gratuitous ARP packets sent +after port is enabled or disabled. +If not set, use teamd default. +.TP +\f[V]TEAM_NOTIFY_PEERS_INTERVAL\f[R] +Value is positive number in milliseconds. +Specifies an interval between bursts of notify-peer packets. +If not set, use teamd default. +.TP +\f[V]TEAM_MCAST_REJOIN_COUNT\f[R] +Number of bursts of multicast group rejoin requests sent after port is +enabled or disabled. +If not set, use teamd default. +.TP +\f[V]TEAM_MCAST_REJOIN_INTERVAL\f[R] +Value is positive number in milliseconds. +Specifies an interval between bursts of multicast group rejoin requests. +If not set, use teamd default. +.TP +\f[V]TEAM_RUNNER\f[R] +must be set to one of the following types to identify this interface as +a team interface: +.RS .PP -.BR "roundrobin "\(em -Team device transmits packets via all its ports with round-robin method. +\f[B]broadcast\f[R] \[en] Team device transmits packets via all its +ports. .PP -.BR "activebackup "\(em -Team device monitors ports' link changes and uses port with active link to transmit packets. +\f[B]roundrobin\f[R] \[en] Team device transmits packets via all its +ports with round-robin method. .PP -.BR "loadbalance "\(em -Team device transmits packets via all its ports performing load balancing (passive or active) with a use of hash functions. For passive load balancing only BPF hash function is used. For active load balancing runner finds best balance by moving hashes between available ports. +\f[B]activebackup\f[R] \[en] Team device monitors ports\[cq] link +changes and uses port with active link to transmit packets. .PP -.BR "lacp "\(em -Implements 802.3ad LACP protocol. +\f[B]loadbalance\f[R] \[en] Team device transmits packets via all its +ports performing load balancing (passive or active) with a use of hash +functions. +For passive load balancing only BPF hash function is used. +For active load balancing runner finds best balance by moving hashes +between available ports. +.PP +\f[B]lacp\f[R] \[en] Implements 802.3ad LACP protocol. .RE .SH ACTIVE-BACKUP RUNNER SPECIFIC OPTIONS - .TP -.BR TEAM_AB_HWADDR_POLICY -Determines the hardware addresses assignment for team device instance and its ports. This assignment is performed during team device instance creation and also for each new port added to the existing instance. +\f[V]TEAM_AB_HWADDR_POLICY\f[R] +Determines the hardware addresses assignment for team device instance +and its ports. +This assignment is performed during team device instance creation and +also for each new port added to the existing instance. The followingi modes are available: -.RS 7 +.RS .PP -.BR "same_all "\(em -All ports will always have the same hardware address as the associated team device. +\f[B]same_all\f[R] \[en] All ports will always have the same hardware +address as the associated team device. .PP -.BR "by_active "\(em -Team device adopts the hardware address of the currently active port. This is useful when the port device is not able to change its hardware address. +\f[B]by_active\f[R] \[en] Team device adopts the hardware address of the +currently active port. +This is useful when the port device is not able to change its hardware +address. .PP -.BR "only_active "\(em -Only the active port adopts the hardware address of the team device. The others have their own. +\f[B]only_active\f[R] \[en] Only the active port adopts the hardware +address of the team device. +The others have their own. .PP -Default: -.BR "same_all" +Default: \f[B]same_all\f[R] .RE -.PP - .SH LOAD BALANCE RUNNER SPECIFIC OPTIONS .TP -.BR TEAM_LB_TX_HASH -A list of string elements separated by a comma ',' which should be used for packet Tx hash computation. +\f[V]TEAM_LB_TX_HASH\f[R] +A list of string elements separated by a comma \[lq]\f[V],\f[R]\[rq] +which should be used for packet Tx hash computation. The following elements are available: -.RS 7 +.RS .PP -.BR "eth "\(em -Uses source and destination MAC addresses. +\f[B]eth\f[R] \[en] Uses source and destination MAC addresses. .PP -.BR "vlan "\(em -Uses VLAN id. +\f[B]vlan\f[R] \[en] Uses VLAN id. .PP -.BR "ipv4 "\(em -Uses source and destination IPv4 addresses. +\f[B]ipv4\f[R] \[en] Uses source and destination IPv4 addresses. .PP -.BR "ipv6 "\(em -Uses source and destination IPv6 addresses. +\f[B]ipv6\f[R] \[en] Uses source and destination IPv6 addresses. .PP -.BR "ip "\(em -Uses source and destination IPv4 and IPv6 addresses. +\f[B]ip\f[R] \[en] Uses source and destination IPv4 and IPv6 addresses. .PP -.BR "l3 "\(em -Uses source and destination IPv4 and IPv6 addresses. +\f[B]l3\f[R] \[en] Uses source and destination IPv4 and IPv6 addresses. .PP -.BR "tcp "\(em -Uses source and destination TCP ports. +\f[B]tcp\f[R] \[en] Uses source and destination TCP ports. .PP -.BR "udp "\(em -Uses source and destination UDP ports. +\f[B]udp\f[R] \[en] Uses source and destination UDP ports. .PP -.BR "sctp "\(em -Uses source and destination SCTP ports. +\f[B]sctp\f[R] \[en] Uses source and destination SCTP ports. .PP -.BR "l4 "\(em -Uses source and destination TCP and UDP and SCTP ports. +\f[B]l4\f[R] \[en] Uses source and destination TCP and UDP and SCTP +ports. .RE .TP -.BR TEAM_LB_TX_BALANCER_NAME -Name of active Tx balancer. Currently only supported value is -.BR "basic". +\f[V]TEAM_LB_TX_BALANCER_NAME\f[R] +Name of active Tx balancer. +Currently only supported value is \f[B]basic\f[R]. .TP -.BR TEAM_LB_TX_BALANCER_INTERVAL -Rebalancing interval. To be specified in tenths of a second. -.RS 7 +\f[V]TEAM_LB_TX_BALANCER_INTERVAL\f[R] +Rebalancing interval. +To be specified in tenths of a second. +.RS .PP Default: 50 .RE - .SH LACP RUNNER SPECIFIC OPTIONS .TP -.BR TEAM_LACP_ACTIVE -Active mode enables sending LACPDU frames through configured link periodically. -.RS 7 +\f[V]TEAM_LACP_ACTIVE\f[R] +Active mode enables sending LACPDU frames through configured link +periodically. +.RS .PP -Default: -.BR "true" +Default: \f[B]true\f[R] .RE .TP -.BR TEAM_LACP_SYS_PRIO -System priority, value can be 0 \(en 65535. +\f[V]TEAM_LACP_SYS_PRIO\f[R] +System priority, value can be 0 - 65535. +.RS .PP -.RS 7 -Default: -.BR "255" +Default: \f[B]255\f[R] .RE .TP -.BR TEAM_LACP_FAST_RATE -Fast rate asks link partner to transmit LACPDU frames once per second. Otherwise they are sent every 30 seconds. -.RS 7 +\f[V]TEAM_LACP_FAST_RATE\f[R] +Fast rate asks link partner to transmit LACPDU frames once per second. +Otherwise they are sent every 30 seconds. +.RS .PP -Default: -.BR "true" +Default: \f[B]true\f[R] .RE .TP -.BR TEAM_LACP_MIN_PORTS -Minimum number of active ports required to assert carrier in master device. Value can be 1 \(en 255. -.RS 7 +\f[V]TEAM_LACP_MIN_PORTS\f[R] +Minimum number of active ports required to assert carrier in master +device. +Value can be 1 - 255. +.RS .PP -Default: -.BR "0" +Default: \f[B]0\f[R] .RE .TP -.BR TEAM_LACP_SELECT_POLICY -The policy of how the aggregators will be selected. The following are available: -.RS 7 -.PP -.BR "lacp_prio "\(em -Aggregator with highest priority according to LACP standard will be selected. Aggregator priority is affected by per-port option -.BR "lacp_prio". -.PP -.BR "lacp_prio_stable "\(em -Same as previous one, except do not replace selected aggregator if it is still usable. -.PP -.BR "bandwidth "\(em -Select aggregator with highest total bandwidth. -.PP -.BR "count "\(em -Select aggregator with highest number of ports. -.PP -.BR "port_options "\(em -Aggregator with highest priority according to per-port options -.BR "prio " and -.BR "sticky " -will be selected. This means that the aggregator containing the port with the highest priority will be selected unless at least one of the ports in the currently selected aggregator is sticky. +\f[V]TEAM_LACP_SELECT_POLICY\f[R] +The policy of how the aggregators will be selected. +The following are available: +.RS .PP -Default: -.BR "lacp_prio" -.RE -.RS 7 -.PP -.BR "lacp_prio "\(em -Aggregator with highest priority according to LACP standard will be selected. Aggregator priority is affected by per-port option -.BR "lacp_prio". +\f[B]lacp_prio\f[R] \[en] Aggregator with highest priority according to +LACP standard will be selected. +Aggregator priority is affected by per-port option \[lq]lacp_prio\[rq]. .PP -.BR "lacp_prio_stable "\(em -Same as previous one, except do not replace selected aggregator if it is still usable. +\f[B]lacp_prio_stable\f[R] \[en] Same as previous one, except do not +replace selected aggregator if it is still usable. .PP -.BR "bandwidth "\(em -Select aggregator with highest total bandwidth. +\f[B]bandwidth\f[R] \[en] Select aggregator with highest total +bandwidth. .PP -.BR "count "\(em -Select aggregator with highest number of ports. +\f[B]count\f[R] \[en] Select aggregator with highest number of ports. .PP -.BR "port_options "\(em -Aggregator with highest priority according to per-port options -.BR "prio " and -.BR "sticky " -will be selected. This means that the aggregator containing the port with the highest priority will be selected unless at least one of the ports in the currently selected aggregator is sticky. +\f[B]port_options\f[R] \[en] Aggregator with highest priority according +to per-port options \f[B]prio\f[R] and \f[B]sticky\f[R] will be +selected. +This means that the aggregator containing the port with the highest +priority will be selected unless at least one of the ports in the +currently selected aggregator is sticky. .PP -Default: -.BR "lacp_prio" +Default: \f[B]lacp_prio\f[R] .RE .TP -.BR TEAM_LACP_TX_HASH -Same as for loadbalancer runner. Please refer to the section above. +\f[V]TEAM_LACP_TX_HASH\f[R] +Same as for loadbalancer runner. +Please refer to the section above. .TP -.BR TEAM_LACP_TX_BALANCER -Same as for loadbalancer runner. Please refer to the section above. +\f[V]TEAM_LACP_TX_BALANCER\f[R] +Same as for loadbalancer runner. +Please refer to the section above. .TP -.BR TEAM_LACP_TX_BALANCER_INTERVAL -Same as for loadbalancer runner. Please refer to the section above. - +\f[V]TEAM_LACP_TX_BALANCER_INTERVAL\f[R] +Same as for loadbalancer runner. +Please refer to the section above. .SH LINK WATCH OPTIONS .TP -.BR TEAM_LW_NAME[SUFFIX] -Declares the type name of link watch (with the specified unique watch suffix). -To declare several link watches, append the same suffix to all variables of one watch. -The following types are available: -.RS 7 +\f[V]TEAM_LINK_WATCH_POLICY\f[R] +Declare name of link-watchers evaluation policy. +The following options are available: +.RS .PP -.BR "ethtool "\(em -Uses Libteam lib to get port ethtool state changes. +\f[B]any\f[R] \[en] Link is up if any of the link-watchers reports the +link up. .PP -.BR "arp_ping "\(em -ARP requests are sent through a port. If an ARP reply is received, the link is considered to be up. +\f[B]all\f[R] \[en] Link is up if all of the link-watchers reports the +link up. .PP -.BR "nsna_ping "\(em -Similar to the previous, except that it uses IPv6 Neighbor Solicitation / Neighbor Advertisement mechanism. +Default: \f[B]any\f[R] +.RE +.TP +\f[V]TEAM_LW_NAME[SUFFIX]\f[R] +Declares the type name of link watch (with the specified unique watch +suffix). +To declare several link watches, append the same suffix to all variables +of one watch. +The following types are available: +.RS .PP +\f[B]ethtool\f[R] \[en] Uses Libteam lib to get port ethtool state +changes. +.PP +\f[B]arp_ping\f[R] \[en] ARP requests are sent through a port. +If an ARP reply is received, the link is considered to be up. +.PP +\f[B]nsna_ping\f[R] \[en] Similar to the previous, except that it uses +IPv6 Neighbor Solicitation / Neighbor Advertisement mechanism. .RE - .SH ETHTOOL LINK WATCH SPECIFIC OPTIONS .TP -.BR TEAM_LW_ETHTOOL_DELAY_UP[SUFFIX] -Delay between the link coming up and the runner being notified about it (in milliseconds). -.RS 7 +\f[V]TEAM_LW_ETHTOOL_DELAY_UP[SUFFIX]\f[R] +Delay between the link coming up and the runner being notified about it +(in milliseconds). +.RS .PP -Default: -.BR "0" +Default: \f[B]0\f[R] .RE .TP -.BR TEAM_LW_ETHTOOL_DELAY_DOWN[SUFFIX] -Delay between the link going down and the runner being notified about it (in milliseconds). -.RS 7 +\f[V]TEAM_LW_ETHTOOL_DELAY_DOWN[SUFFIX]\f[R] +Delay between the link going down and the runner being notified about it +(in milliseconds). +.RS .PP -Default: -.BR "0" +Default: \f[B]0\f[R] .RE - .SH ARP PING LINK WATCH SPECIFIC OPTIONS .TP -.BR TEAM_LW_ARP_PING_SOURCE_HOST[SUFFIX] +\f[V]TEAM_LW_ARP_PING_SOURCE_HOST[SUFFIX]\f[R] Hostname or IP address used in ARP request as source address. -.RS 7 +.RS .PP -Default: -.BR "0.0.0.0" +Default: \f[B]0.0.0.0\f[R] .RE .TP -.BR TEAM_LW_ARP_PING_TARGET_HOST[SUFFIX] +\f[V]TEAM_LW_ARP_PING_TARGET_HOST[SUFFIX]\f[R] Hostname or IP address used in ARP request as destination address. .TP -.BR TEAM_LW_ARP_PING_INTERVAL[SUFFIX] +\f[V]TEAM_LW_ARP_PING_INTERVAL[SUFFIX]\f[R] Interval between ARP requests being sent (in milliseconds). .TP -.BR TEAM_LW_ARP_PING_INIT_WAIT[SUFFIX] -Delay between link watch initialization and the first ARP request being sent (in milliseconds). -.RS 7 +\f[V]TEAM_LW_ARP_PING_INIT_WAIT[SUFFIX]\f[R] +Delay between link watch initialization and the first ARP request being +sent (in milliseconds). +.RS .PP -Default: -.BR "0" +Default: \f[B]0\f[R] .RE .TP -.BR TEAM_LW_ARP_PING_VALIDATE_ACTIVE[SUFFIX] -Validate received ARP packets on active ports. Otherwise all incoming ARP packets will be considered as a good reply. -.RS 7 +\f[V]TEAM_LW_ARP_PING_VALIDATE_ACTIVE[SUFFIX]\f[R] +Validate received ARP packets on active ports. +Otherwise all incoming ARP packets will be considered as a good reply. +.RS .PP -Default: -.BR "false" +Default: \f[B]false\f[R] .RE .TP -.BR TEAM_LW_ARP_PING_VALIDATE_INACTIVE[SUFFIX] -Validate received ARP packets on inactive ports. Otherwise all incoming ARP packets will be considered as a good reply. -.RS 7 +\f[V]TEAM_LW_ARP_PING_VALIDATE_INACTIVE[SUFFIX]\f[R] +Validate received ARP packets on inactive ports. +Otherwise all incoming ARP packets will be considered as a good reply. +.RS .PP -Default: -.BR "false" +Default: \f[B]false\f[R] .RE .TP -.BR TEAM_LW_ARP_PING_SEND_ALWAYS[SUFFIX] +\f[V]TEAM_LW_ARP_PING_SEND_ALWAYS[SUFFIX]\f[R] Allow sending ARP requests on inactive ports. -.RS 7 -.PP -Default: -.BR "false" +.RS .PP +Default: \f[B]false\f[R] .RE .TP -.BR TEAM_LW_ARP_PING_MISSED_MAX[SUFFIX] -Maximum number of missed ARP replies. If this number is exceeded, link is reported as down. -.RS 7 +\f[V]TEAM_LW_ARP_PING_MISSED_MAX[SUFFIX]\f[R] +Maximum number of missed ARP replies. +If this number is exceeded, link is reported as down. +.RS .PP -Default: -.BR "3" +Default: \f[B]3\f[R] .RE - +.TP +\f[V]TEAM_LW_ARP_PING_VLANID[SUFFIX]\f[R] +By default, ARP requests are sent without VLAN tags. +This option causes outgoing ARP requests to be sent with the specified +VLAN ID number. .SH NS/NA PING LINK WATCH SPECIFIC OPTIONS .TP -.BR TEAM_LW_NSNA_PING_TARGET_HOST[SUFFIX] +\f[V]TEAM_LW_NSNA_PING_TARGET_HOST[SUFFIX]\f[R] Hostname or IPv6 address used in NS packet as target address. .TP -.BR TEAM_LW_NSNA_PING_INTERVAL[SUFFIX] +\f[V]TEAM_LW_NSNA_PING_INTERVAL[SUFFIX]\f[R] Interval between sending NS packets (in milliseconds). .TP -.BR TEAM_LW_NSNA_PING_INIT_WAIT[SUFFIX] -Delay between link watch initialization and the first NS packet being sent (in milliseconds). +\f[V]TEAM_LW_NSNA_PING_INIT_WAIT[SUFFIX]\f[R] +Delay between link watch initialization and the first NS packet being +sent (in milliseconds). .TP -.BR TEAM_LW_NSNA_PING_MISSED_MAX[SUFFIX] -Maximum number of missed NA reply packets. If this number is exceeded, link is reported as down. -.RS 7 +\f[V]TEAM_LW_NSNA_PING_MISSED_MAX[SUFFIX]\f[R] +Maximum number of missed NA reply packets. +If this number is exceeded, link is reported as down. +.RS .PP -Default: -.BR "3" +Default: \f[B]3\f[R] .RE - .SH TEAM PORT SPECIFIC OPTIONS - .TP -.BR TEAM_PORT_DEVICE[SUFFIX] -Port device name. This option must not be empty for a given port. - +\f[V]TEAM_PORT_DEVICE[SUFFIX]\f[R] +Port device name. +This option must not be empty for a given port. .TP -.BR TEAM_PORT_QUEUE_ID[SUFFIX] +\f[V]TEAM_PORT_QUEUE_ID[SUFFIX]\f[R] ID of queue which this port should be mapped to. -.RS 7 +.RS .PP -Default: -.BR "None" +Default: \f[B]None\f[R] .RE - .TP -.BR TEAM_PORT_STICKY[SUFFIX] -Marks an activebackup runner port as sticky, to not deselect it, if another -port with a higher priority or better parameters becomes available. -.RS 7 +\f[V]TEAM_PORT_STICKY[SUFFIX]\f[R] +Marks an activebackup runner port as sticky, to not deselect it, if +another port with a higher priority or better parameters becomes +available. +.RS .PP -Default: -.BR "false" +Default: \f[B]false\f[R] .RE - .TP -.BR TEAM_PORT_PRIO[SUFFIX] -Port priority in activebackup runner. The higher number means higher priority. -.RS 7 +\f[V]TEAM_PORT_PRIO[SUFFIX]\f[R] +Port priority in activebackup runner. +The higher number means higher priority. +.RS .PP -Default: -.BR "0" +Default: \f[B]0\f[R] .RE - .TP -.BR TEAM_PORT_LACP_PRIO[SUFFIX] -Port priority according to LACP standard. The lower number means higher priority. -.RS 7 +\f[V]TEAM_PORT_LACP_PRIO[SUFFIX]\f[R] +Port priority according to LACP standard. +The lower number means higher priority. +.RS .PP -Default: -.BR "0" +Default: \f[B]0\f[R] .RE - .TP -.BR TEAM_PORT_LACP_KEY[SUFFIX] -Port key according to LACP standard. It is only possible to aggregate ports with -the same key. -.RS 7 +\f[V]TEAM_PORT_LACP_KEY[SUFFIX]\f[R] +Port key according to LACP standard. +It is only possible to aggregate ports with the same key. +.RS .PP -Default: -.BR "0" +Default: \f[B]0\f[R] .RE - - -.SH Example -Example for a bonding interface on eth0 and eth1 using the backup mode - -.I ifcfg-team0 +.SH EXAMPLE +.PP +Example for a teaming interface on eth0 and eth1 using the backup mode +.IP .nf +\f[C] STARTMODE=auto BOOTPROTO=static #IPADDR=... - TEAM_RUNNER="loadbalance" - TEAM_LB_TX_HASH="ipv4,ipv6,eth,vlan" - TEAM_LB_TX_BALANCER_NAME="basic" - TEAM_LB_TX_BALANCER_INTERVAL="100" + TEAM_RUNNER=\[dq]loadbalance\[dq] + TEAM_LB_TX_HASH=\[dq]ipv4,ipv6,eth,vlan\[dq] + TEAM_LB_TX_BALANCER_NAME=\[dq]basic\[dq] + TEAM_LB_TX_BALANCER_INTERVAL=\[dq]100\[dq] - TEAM_PORT_DEVICE_1="eth1" - TEAM_PORT_DEVICE_2="eth2" + TEAM_PORT_DEVICE_1=\[dq]eth1\[dq] + TEAM_PORT_DEVICE_2=\[dq]eth2\[dq] - TEAM_LW_NAME="ethtool" - TEAM_LW_ETHTOOL_DELAY_UP="10" - TEAM_LW_ETHTOOL_DELAY_DOWN="10" + TEAM_LW_NAME=\[dq]ethtool\[dq] + TEAM_LW_ETHTOOL_DELAY_UP=\[dq]10\[dq] + TEAM_LW_ETHTOOL_DELAY_DOWN=\[dq]10\[dq] # optionally, further watches, e.g: - TEAM_LW_NAME_1="nsna_ping" - TEAM_LW_NSNA_PING_INTERVAL_1="100" - TEAM_LW_NSNA_PING_MISSED_MAX_1="30" - TEAM_LW_NSNA_PING_TARGET_HOST="fe80::1" + TEAM_LW_NAME_1=\[dq]nsna_ping\[dq] + TEAM_LW_NSNA_PING_INTERVAL_1=\[dq]100\[dq] + TEAM_LW_NSNA_PING_MISSED_MAX_1=\[dq]30\[dq] + TEAM_LW_NSNA_PING_TARGET_HOST_1=\[dq]fe80::1\[dq] +\f[R] .fi - .SH Additional Information - +.PP For additional and more general information take a look into -.BR https://github.com/jpirko/libteam/wiki -or -.BR teamd.conf (5). - -The configuration of routes for this kind of interface does not differ from -ordinary interfaces. See -.I man routes -for details. - + or \f[I]teamd.conf\f[R](5). +.PP +The configuration of routes for this kind of interface does not differ +from ordinary interfaces. +See \f[I]man routes\f[R] for details. .SH COPYRIGHT -Copyright (C) 2015 SUSE Linux GmbH, Nuernberg, Germany. +.PP +Copyright (C) 2015-2022 SUSE LLC .SH BUGS +.PP Please report bugs at -.SH AUTHOR -.nf -Pawel Wieczorkiewicz -- original team man page -.fi -.SH "SEE ALSO" -.BR teamd.conf (5), -.BR ifcfg (5), -.BR wicked (8), -.BR teamd (8), -.BR teamdctl (8). +.SH SEE ALSO +.PP +\f[B]\f[VB]teamd.conf\f[B]\f[R] (5), \f[B]\f[VB]ifcfg\f[B]\f[R] (5), +\f[B]\f[VB]wicked\f[B]\f[R] (8), \f[B]\f[VB]teamd\f[B]\f[R] (8), +\f[B]\f[VB]teamdctl\f[B]\f[R] (8) +.SH AUTHORS +Pawel Wieczorkiewicz \[en] original wireless man page, Clemens +Famulla-Conrad. diff --git a/man/src/ifcfg-team.5.md b/man/src/ifcfg-team.5.md new file mode 100644 index 000000000..65ab9f878 --- /dev/null +++ b/man/src/ifcfg-team.5.md @@ -0,0 +1,365 @@ +% IFCFG-TEAM(5) Wicked User Manual +% Pawel Wieczorkiewicz -- original wireless man page, Clemens Famulla-Conrad +% January 29, 2024 + +# NAME +ifcfg-team - interface team configuration + +# SYNOPSIS +`/etc/sysconfig/network/ifcfg-*` + + +# Team Interfaces + +To setup a team interface you need a configuration file ifcfg-team<X> with +the usual network settings. But you must add additional variables + +`TEAM_DEBUG_LEVEL` +: Level of debug messages. The higher it is the more debug messages will + be printed. + + Default: **0** (disabled) + +`TEAM_NOTIFY_PEERS_COUNT` +: Number of bursts of unsolicited NAs and gratuitous ARP packets sent + after port is enabled or disabled. If not set, use teamd default. + +`TEAM_NOTIFY_PEERS_INTERVAL` +: Value is positive number in milliseconds. Specifies an interval between + bursts of notify-peer packets. If not set, use teamd default. + +`TEAM_MCAST_REJOIN_COUNT` +: Number of bursts of multicast group rejoin requests sent after port is + enabled or disabled. If not set, use teamd default. + +`TEAM_MCAST_REJOIN_INTERVAL` +: Value is positive number in milliseconds. Specifies an interval between + bursts of multicast group rejoin requests. If not set, use teamd default. + +`TEAM_RUNNER` +: must be set to one of the following types to identify this interface as + a team interface: + + **broadcast** -- Team device transmits packets via all its ports. + + **roundrobin** -- Team device transmits packets via all its ports with + round-robin method. + + **activebackup** -- Team device monitors ports' link changes and uses + port with active link to transmit packets. + + **loadbalance** -- Team device transmits packets via all its ports + performing load balancing (passive or active) with a use of hash functions. + For passive load balancing only BPF hash function is used. For active load + balancing runner finds best balance by moving hashes between available + ports. + + **lacp** -- Implements 802.3ad LACP protocol. + + +# ACTIVE-BACKUP RUNNER SPECIFIC OPTIONS + +`TEAM_AB_HWADDR_POLICY` +: Determines the hardware addresses assignment for team device instance and + its ports. This assignment is performed during team device instance creation + and also for each new port added to the existing instance. + The followingi modes are available: + + **same_all** -- All ports will always have the same hardware address as the + associated team device. + + **by_active** -- Team device adopts the hardware address of the currently + active port. This is useful when the port device is not able to change + its hardware address. + + **only_active** -- Only the active port adopts the hardware address of the + team device. The others have their own. + + Default: **same_all** + + +# LOAD BALANCE RUNNER SPECIFIC OPTIONS + +`TEAM_LB_TX_HASH` +: A list of string elements separated by a comma "`,`" + which should be used for packet Tx hash computation. + The following elements are available: + + **eth** -- Uses source and destination MAC addresses. + + **vlan** -- Uses VLAN id. + + **ipv4** -- Uses source and destination IPv4 addresses. + + **ipv6** -- Uses source and destination IPv6 addresses. + + **ip** -- Uses source and destination IPv4 and IPv6 addresses. + + **l3** -- Uses source and destination IPv4 and IPv6 addresses. + + **tcp** -- Uses source and destination TCP ports. + + **udp** -- Uses source and destination UDP ports. + + **sctp** -- Uses source and destination SCTP ports. + + **l4** -- Uses source and destination TCP and UDP and SCTP ports. + +`TEAM_LB_TX_BALANCER_NAME` +: Name of active Tx balancer. Currently only supported value is **basic**. + +`TEAM_LB_TX_BALANCER_INTERVAL` +: Rebalancing interval. To be specified in tenths of a second. + + Default: 50 + + +# LACP RUNNER SPECIFIC OPTIONS + +`TEAM_LACP_ACTIVE` +: Active mode enables sending LACPDU frames through configured link + periodically. + + Default: **true** + +`TEAM_LACP_SYS_PRIO` +: System priority, value can be 0 - 65535. + + Default: **255** + +`TEAM_LACP_FAST_RATE` +: Fast rate asks link partner to transmit LACPDU frames once per second. + Otherwise they are sent every 30 seconds. + + Default: **true** + +`TEAM_LACP_MIN_PORTS` +: Minimum number of active ports required to assert carrier in master device. + Value can be 1 - 255. + + Default: **0** + +`TEAM_LACP_SELECT_POLICY` +: The policy of how the aggregators will be selected. The following are + available: + + **lacp_prio** -- Aggregator with highest priority according to LACP + standard will be selected. Aggregator priority is affected by per-port + option "lacp_prio". + + **lacp_prio_stable** -- Same as previous one, except do not replace + selected aggregator if it is still usable. + + **bandwidth** -- Select aggregator with highest total bandwidth. + + **count** -- Select aggregator with highest number of ports. + + **port_options** -- Aggregator with highest priority according to per-port + options **prio** and **sticky** will be selected. This means that the + aggregator containing the port with the highest priority will be selected + unless at least one of the ports in the currently selected aggregator is + sticky. + + Default: **lacp_prio** + +`TEAM_LACP_TX_HASH` +: Same as for loadbalancer runner. Please refer to the section above. + +`TEAM_LACP_TX_BALANCER` +: Same as for loadbalancer runner. Please refer to the section above. + +`TEAM_LACP_TX_BALANCER_INTERVAL` +: Same as for loadbalancer runner. Please refer to the section above. + + +# LINK WATCH OPTIONS + +`TEAM_LINK_WATCH_POLICY` +: Declare name of link-watchers evaluation policy. The following options are + available: + + **any** -- Link is up if any of the link-watchers reports the link up. + + **all** -- Link is up if all of the link-watchers reports the link up. + + Default: **any** + +`TEAM_LW_NAME[SUFFIX]` +: Declares the type name of link watch (with the specified unique watch + suffix). To declare several link watches, append the same suffix to all + variables of one watch. The following types are available: + + **ethtool** -- Uses Libteam lib to get port ethtool state changes. + + **arp_ping** -- ARP requests are sent through a port. If an ARP reply is + received, the link is considered to be up. + + **nsna_ping** -- Similar to the previous, except that it uses IPv6 Neighbor + Solicitation / Neighbor Advertisement mechanism. + + +# ETHTOOL LINK WATCH SPECIFIC OPTIONS + +`TEAM_LW_ETHTOOL_DELAY_UP[SUFFIX]` +: Delay between the link coming up and the runner being notified about it + (in milliseconds). + + Default: **0** + +`TEAM_LW_ETHTOOL_DELAY_DOWN[SUFFIX]` +: Delay between the link going down and the runner being notified about it + (in milliseconds). + + Default: **0** + + +# ARP PING LINK WATCH SPECIFIC OPTIONS + +`TEAM_LW_ARP_PING_SOURCE_HOST[SUFFIX]` +: Hostname or IP address used in ARP request as source address. + + Default: **0.0.0.0** + +`TEAM_LW_ARP_PING_TARGET_HOST[SUFFIX]` +: Hostname or IP address used in ARP request as destination address. + +`TEAM_LW_ARP_PING_INTERVAL[SUFFIX]` +: Interval between ARP requests being sent (in milliseconds). + +`TEAM_LW_ARP_PING_INIT_WAIT[SUFFIX]` +: Delay between link watch initialization and the first ARP request being + sent (in milliseconds). + + Default: **0** + +`TEAM_LW_ARP_PING_VALIDATE_ACTIVE[SUFFIX]` +: Validate received ARP packets on active ports. Otherwise all incoming ARP + packets will be considered as a good reply. + + Default: **false** + +`TEAM_LW_ARP_PING_VALIDATE_INACTIVE[SUFFIX]` +: Validate received ARP packets on inactive ports. Otherwise all incoming ARP + packets will be considered as a good reply. + + Default: **false** + +`TEAM_LW_ARP_PING_SEND_ALWAYS[SUFFIX]` +: Allow sending ARP requests on inactive ports. + + Default: **false** + +`TEAM_LW_ARP_PING_MISSED_MAX[SUFFIX]` +: Maximum number of missed ARP replies. If this number is exceeded, link is + reported as down. + + Default: **3** + +`TEAM_LW_ARP_PING_VLANID[SUFFIX]` +: By default, ARP requests are sent without VLAN tags. This option causes + outgoing ARP requests to be sent with the specified VLAN ID number. + + +# NS/NA PING LINK WATCH SPECIFIC OPTIONS + +`TEAM_LW_NSNA_PING_TARGET_HOST[SUFFIX]` +: Hostname or IPv6 address used in NS packet as target address. + +`TEAM_LW_NSNA_PING_INTERVAL[SUFFIX]` +: Interval between sending NS packets (in milliseconds). + +`TEAM_LW_NSNA_PING_INIT_WAIT[SUFFIX]` +: Delay between link watch initialization and the first NS packet being sent + (in milliseconds). + +`TEAM_LW_NSNA_PING_MISSED_MAX[SUFFIX]` +: Maximum number of missed NA reply packets. If this number is exceeded, link + is reported as down. + + Default: **3** + + +# TEAM PORT SPECIFIC OPTIONS + +`TEAM_PORT_DEVICE[SUFFIX]` +: Port device name. This option must not be empty for a given port. + +`TEAM_PORT_QUEUE_ID[SUFFIX]` +: ID of queue which this port should be mapped to. + + Default: **None** + + +`TEAM_PORT_STICKY[SUFFIX]` +: Marks an activebackup runner port as sticky, to not deselect it, if another + port with a higher priority or better parameters becomes available. + + Default: **false** + + +`TEAM_PORT_PRIO[SUFFIX]` +: Port priority in activebackup runner. The higher number means higher + priority. + + Default: **0** + + +`TEAM_PORT_LACP_PRIO[SUFFIX]` +: Port priority according to LACP standard. The lower number means higher + priority. + + Default: **0** + + +`TEAM_PORT_LACP_KEY[SUFFIX]` +: Port key according to LACP standard. It is only possible to aggregate ports + with the same key. + + Default: **0** + + +# EXAMPLE + +Example for a teaming interface on eth0 and eth1 using the backup mode + +``` + STARTMODE=auto + BOOTPROTO=static + #IPADDR=... + + TEAM_RUNNER="loadbalance" + TEAM_LB_TX_HASH="ipv4,ipv6,eth,vlan" + TEAM_LB_TX_BALANCER_NAME="basic" + TEAM_LB_TX_BALANCER_INTERVAL="100" + + TEAM_PORT_DEVICE_1="eth1" + TEAM_PORT_DEVICE_2="eth2" + + TEAM_LW_NAME="ethtool" + TEAM_LW_ETHTOOL_DELAY_UP="10" + TEAM_LW_ETHTOOL_DELAY_DOWN="10" + # optionally, further watches, e.g: + TEAM_LW_NAME_1="nsna_ping" + TEAM_LW_NSNA_PING_INTERVAL_1="100" + TEAM_LW_NSNA_PING_MISSED_MAX_1="30" + TEAM_LW_NSNA_PING_TARGET_HOST_1="fe80::1" +``` + +# Additional Information + +For additional and more general information take a look into + or *teamd.conf*(5). + +The configuration of routes for this kind of interface does not differ from +ordinary interfaces. See *man routes* for details. + + +# COPYRIGHT +Copyright (C) 2015-2022 SUSE LLC + +# BUGS +Please report bugs at + +# SEE ALSO +**`teamd.conf`** (5), **`ifcfg`** (5), **`wicked`** (8), **`teamd`** (8), +**`teamdctl`** (8) diff --git a/schema/constants.xml.in b/schema/constants.xml.in index 3fba19962..8f3f9e3b7 100644 --- a/schema/constants.xml.in +++ b/schema/constants.xml.in @@ -211,6 +211,9 @@ <@@TEAM_LACP_SELECT_POLICY_NAME@@ value="@@TEAM_LACP_SELECT_POLICY_VALUE@@"/> + + <@@TEAM_LINK_WATCH_POLICY_NAME@@ value="@@TEAM_LINK_WATCH_POLICY_VALUE@@"/> + diff --git a/schema/team.xml b/schema/team.xml index d6c3a11ca..dcfa46d68 100644 --- a/schema/team.xml +++ b/schema/team.xml @@ -49,6 +49,7 @@ + @@ -84,6 +85,15 @@ + + + + + + + + + @@ -92,7 +102,7 @@ - + diff --git a/src/dbus-objects/team.c b/src/dbus-objects/team.c index 84fa95cef..0fb9e931a 100644 --- a/src/dbus-objects/team.c +++ b/src/dbus-objects/team.c @@ -248,8 +248,8 @@ __ni_objectmodel_delete_team(ni_dbus_object_t *object, const ni_dbus_method_t *m /* * Helper function to obtain team config from dbus object */ -static ni_team_t * -__ni_objectmodel_team_handle(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) +static void * +ni_objectmodel_get_team(const ni_dbus_object_t *object, ni_bool_t write_access, DBusError *error) { ni_netdev_t *dev; ni_team_t *team; @@ -270,13 +270,13 @@ __ni_objectmodel_team_handle(const ni_dbus_object_t *object, ni_bool_t write_acc static ni_team_t * __ni_objectmodel_team_write_handle(const ni_dbus_object_t *object, DBusError *error) { - return __ni_objectmodel_team_handle(object, TRUE, error); + return ni_objectmodel_get_team(object, TRUE, error); } static const ni_team_t * __ni_objectmodel_team_read_handle(const ni_dbus_object_t *object, DBusError *error) { - return __ni_objectmodel_team_handle(object, FALSE, error); + return ni_objectmodel_get_team(object, FALSE, error); } #if 0 @@ -309,6 +309,102 @@ __ni_objectmodel_team_set_address(ni_dbus_object_t *object, const ni_dbus_proper return __ni_objectmodel_set_hwaddr(argument, &dev->link.hwaddr); } +static dbus_bool_t +__ni_objectmodel_team_get_mcast_rejoin(const ni_dbus_object_t *object, const ni_dbus_property_t *property, + ni_dbus_variant_t *result, DBusError *error) +{ + const ni_team_t *team; + const ni_team_mcast_rejoin_t *m; + + if (!(team = __ni_objectmodel_team_read_handle(object, error))) + return FALSE; + m = &team->mcast_rejoin; + + if (m->count == -1U && m->interval == -1U) + return ni_dbus_error_property_not_present(error, object->path, property->name); + + ni_dbus_variant_init_dict(result); + if (m->count != -1U) + ni_dbus_dict_add_uint32(result, "count", m->count); + + if (m->interval != -1U) + ni_dbus_dict_add_uint32(result, "interval", m->interval); + + return TRUE; +} + +static dbus_bool_t +__ni_objectmodel_team_set_mcast_rejoin(ni_dbus_object_t *object, const ni_dbus_property_t *property, + const ni_dbus_variant_t *argument, DBusError *error) +{ + ni_team_t *team; + uint32_t u32; + + if (!(team = __ni_objectmodel_team_write_handle(object, error))) + return FALSE; + + if (!ni_dbus_variant_is_dict(argument)) { + dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "team mcast_rejoin member is not a dict"); + return FALSE; + } + + if (ni_dbus_dict_get_uint32(argument, "count", &u32)) + team->mcast_rejoin.count = u32; + + if (ni_dbus_dict_get_uint32(argument, "interval", &u32)) + team->mcast_rejoin.interval = u32; + + return TRUE; +} + +static dbus_bool_t +__ni_objectmodel_team_get_notify_peers(const ni_dbus_object_t *object, const ni_dbus_property_t *property, + ni_dbus_variant_t *result, DBusError *error) +{ + const ni_team_t *team; + const ni_team_notify_peers_t *m; + + if (!(team = __ni_objectmodel_team_read_handle(object, error))) + return FALSE; + m = &team->notify_peers; + + if (m->count == -1U && m->interval == -1U) + return ni_dbus_error_property_not_present(error, object->path, property->name); + + ni_dbus_variant_init_dict(result); + if (m->count != -1U) + ni_dbus_dict_add_uint32(result, "count", m->count); + + if (m->interval != -1U) + ni_dbus_dict_add_uint32(result, "interval", m->interval); + + return TRUE; +} + +static dbus_bool_t +__ni_objectmodel_team_set_notify_peers(ni_dbus_object_t *object, const ni_dbus_property_t *property, + const ni_dbus_variant_t *argument, DBusError *error) +{ + ni_team_t *team; + uint32_t u32; + + if (!(team = __ni_objectmodel_team_write_handle(object, error))) + return FALSE; + + if (!ni_dbus_variant_is_dict(argument)) { + dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "team notify_peers member is not a dict"); + return FALSE; + } + + if (ni_dbus_dict_get_uint32(argument, "count", &u32)) + team->notify_peers.count = u32; + + if (ni_dbus_dict_get_uint32(argument, "interval", &u32)) + team->notify_peers.interval = u32; + + return TRUE; +} + static dbus_bool_t __ni_objectmodel_team_get_runner(const ni_dbus_object_t *object, const ni_dbus_property_t *property, ni_dbus_variant_t *result, DBusError *error) @@ -545,6 +641,8 @@ __ni_objectmodel_team_link_watch_to_dict(const ni_team_link_watch_t *lw, ni_dbus ni_dbus_dict_add_bool(dict, "send_always", lw->arp.send_always); if (lw->arp.missed_max > 0) ni_dbus_dict_add_uint32(dict, "missed_max", lw->arp.missed_max); + if (lw->arp.vlanid != UINT16_MAX) + ni_dbus_dict_add_uint16(dict, "vlanid", lw->arp.vlanid); break; case NI_TEAM_LINK_WATCH_NSNA_PING: if (lw->nsna.target_host) @@ -574,6 +672,7 @@ __ni_objectmodel_team_link_watch_from_dict(ni_team_link_watch_t *lw, const ni_db const char *string; dbus_bool_t bvalue; uint32_t value; + uint16_t u16; if (!lw || !dict || !error) return FALSE; @@ -602,6 +701,8 @@ __ni_objectmodel_team_link_watch_from_dict(ni_team_link_watch_t *lw, const ni_db lw->arp.send_always = bvalue; if (ni_dbus_dict_get_uint32(dict, "missed_max", &value)) lw->arp.missed_max = value; + if (ni_dbus_dict_get_uint16(dict, "vlanid", &u16)) + lw->arp.vlanid = u16; break; case NI_TEAM_LINK_WATCH_NSNA_PING: if (ni_dbus_dict_get_string(dict, "target_host", &string)) @@ -883,12 +984,19 @@ __ni_objectmodel_team_set_ports(ni_dbus_object_t *object, const ni_dbus_property #define TEAM_DICT_PROPERTY(dbus_name, member_name,rw) \ ___NI_DBUS_PROPERTY(NI_DBUS_DICT_SIGNATURE, dbus_name, \ member_name, __ni_objectmodel_team, RO) +#define TEAM_UINT_PROPERTY(dbus_name, member_name, rw) \ + NI_DBUS_GENERIC_UINT_PROPERTY(team, dbus_name, member_name, rw) + #define TEAM_DICT_ARRAY_PROPERTY(dbus_name, member_name,rw) \ ___NI_DBUS_PROPERTY(DBUS_TYPE_ARRAY_AS_STRING NI_DBUS_DICT_SIGNATURE, \ dbus_name, member_name, __ni_objectmodel_team, RO) static ni_dbus_property_t ni_objectmodel_team_properties[] = { + TEAM_UINT_PROPERTY(debug_level, debug_level, RO), + TEAM_DICT_PROPERTY(notify_peers, notify_peers, RO), + TEAM_DICT_PROPERTY(mcast_rejoin, mcast_rejoin, RO), TEAM_DICT_PROPERTY(runner, runner, RO), + TEAM_UINT_PROPERTY(link_watch_policy, link_watch_policy, RO), TEAM_DICT_PROPERTY(link_watch, link_watch, RO), TEAM_DICT_ARRAY_PROPERTY(ports, ports, RO), TEAM_HWADDR_PROPERTY(address, RO), diff --git a/src/team.c b/src/team.c index 068407aab..1451296cb 100644 --- a/src/team.c +++ b/src/team.c @@ -256,6 +256,24 @@ ni_team_link_watch_name_to_type(const char *name, ni_team_link_watch_type_t *typ return TRUE; } +void +ni_team_link_watch_init(ni_team_link_watch_t *lw) +{ + if (lw) switch (lw->type) { + case NI_TEAM_LINK_WATCH_ETHTOOL: + break; + case NI_TEAM_LINK_WATCH_ARP_PING: + lw->arp.vlanid = UINT16_MAX; + break; + case NI_TEAM_LINK_WATCH_NSNA_PING: + break; + case NI_TEAM_LINK_WATCH_TIPC: + break; + default: + return; + } +} + /* * team master link watch */ @@ -267,6 +285,7 @@ ni_team_link_watch_new(ni_team_link_watch_type_t type) lw = xcalloc(1, sizeof(*lw)); lw->type = type; + ni_team_link_watch_init(lw); return lw; } @@ -292,6 +311,34 @@ ni_team_link_watch_free(ni_team_link_watch_t *lw) free(lw); } +/* + * Map teamd link watch policy to constants + */ +static const ni_intmap_t ni_team_link_watch_policy[] = { + { "any", NI_TEAM_LINK_WATCH_POLICY_ANY }, + { "all", NI_TEAM_LINK_WATCH_POLICY_ALL }, + + { NULL, -1U } +}; + +const char * +ni_team_link_watch_policy_type_to_name(ni_team_link_watch_policy_t type) +{ + return ni_format_uint_mapped(type, ni_team_link_watch_policy); +} + +ni_bool_t +ni_team_link_watch_policy_name_to_type(const char *name, ni_team_link_watch_policy_t *type) +{ + if (!name || !type) + return FALSE; + + if (ni_parse_uint_mapped(name, ni_team_link_watch_policy, type) != 0) + return FALSE; + + return TRUE; +} + static ni_define_ptr_array_init(ni_team_link_watch); static ni_define_ptr_array_destroy(ni_team_link_watch); static ni_define_ptr_array_realloc(ni_team_link_watch, NI_TEAM_LINK_WATCH_ARRAY_CHUNK); @@ -354,6 +401,15 @@ ni_team_port_config_destroy(ni_team_port_config_t *pc) { } +static void +ni_team_init(ni_team_t *team) +{ + team->notify_peers.count = -1U; + team->notify_peers.interval = -1U; + team->mcast_rejoin.count = -1U; + team->mcast_rejoin.interval = -1U; +} + /* * team device */ @@ -363,6 +419,8 @@ ni_team_new(void) ni_team_t *team; team = xcalloc(1, sizeof(*team)); + ni_team_init(team); + return team; } diff --git a/src/teamd.c b/src/teamd.c index e6cb26798..0a5d0a0ed 100644 --- a/src/teamd.c +++ b/src/teamd.c @@ -936,6 +936,8 @@ ni_teamd_discover_link_watch_item_details(ni_team_link_watch_t *lw, ni_json_t *l lw->arp.send_always= b; if (ni_json_int64_get(ni_json_object_get_value(link_watch, "missed_max"), &i64)) lw->arp.missed_max= i64; + if (ni_json_int64_get(ni_json_object_get_value(link_watch, "vlanid"), &i64)) + lw->arp.vlanid = (uint16_t)i64; break; case NI_TEAM_LINK_WATCH_NSNA_PING: @@ -960,6 +962,19 @@ ni_teamd_discover_link_watch_item_details(ni_team_link_watch_t *lw, ni_json_t *l return 0; } + +static void +ni_teamd_discover_link_watch_policy(ni_netdev_t *dev, ni_team_t *team, ni_json_t *conf) +{ + char * name = NULL; + + if (!ni_json_string_get(ni_json_object_get_value(conf, "link_watch_policy"), &name)) + return; + + if (!ni_team_link_watch_policy_name_to_type(name, &team->link_watch_policy)) + ni_warn("%s: Unknown link_watch_policy value %s", dev->name, name); +} + static int ni_teamd_discover_link_watch_item(ni_team_link_watch_array_t *array, ni_json_t *link_watch) { @@ -1103,6 +1118,38 @@ ni_teamd_discover_ports(ni_team_t *team, ni_json_t *conf) return 0; } +static void +ni_teamd_discover_notify_peers(ni_team_t *team, ni_json_t *conf) +{ + int64_t i64; + ni_json_t *json; + + if (!team || !conf || !(json = ni_json_object_get_value(conf, "notify_peers"))) + return; + + if (ni_json_int64_get(ni_json_object_get_value(json, "count"), &i64)) + team->notify_peers.count = i64; + + if (ni_json_int64_get(ni_json_object_get_value(json, "interval"), &i64)) + team->notify_peers.interval = i64; +} + +static void +ni_teamd_discover_mcast_rejoin(ni_team_t *team, ni_json_t *conf) +{ + int64_t i64; + ni_json_t *json; + + if (!team || !conf || !(json = ni_json_object_get_value(conf, "mcast_rejoin"))) + return; + + if (ni_json_int64_get(ni_json_object_get_value(json, "count"), &i64)) + team->mcast_rejoin.count = i64; + + if (ni_json_int64_get(ni_json_object_get_value(json, "interval"), &i64)) + team->mcast_rejoin.interval = i64; +} + int ni_teamd_discover(ni_netdev_t *dev) { @@ -1110,6 +1157,7 @@ ni_teamd_discover(ni_netdev_t *dev) ni_json_t *conf = NULL; ni_team_t *team = NULL; char *val = NULL; + int64_t i64; if (!dev || dev->link.type != NI_IFTYPE_TEAM) return -1; @@ -1128,9 +1176,17 @@ ni_teamd_discover(ni_netdev_t *dev) if (!(conf = ni_json_parse_string(val))) goto failure; + if (ni_json_int64_get(ni_json_object_get_value(conf, "debug_level"), &i64) && i64 < UINT_MAX) + team->debug_level = i64; + + ni_teamd_discover_notify_peers(team, conf); + ni_teamd_discover_mcast_rejoin(team, conf); + if (ni_teamd_discover_runner(team, conf) < 0) goto failure; + ni_teamd_discover_link_watch_policy(dev, team, conf); + if (ni_teamd_discover_link_watch(team, conf) < 0) goto failure; @@ -1330,6 +1386,9 @@ ni_teamd_config_json_link_watch_item(const ni_team_link_watch_t *lw) if (a->missed_max) { ni_json_object_set(object, "missed_max", ni_json_new_int64(a->missed_max)); } + if (a->vlanid != UINT16_MAX) { + ni_json_object_set(object, "vlanid", ni_json_new_int64(a->vlanid)); + } } break; @@ -1386,11 +1445,50 @@ ni_teamd_config_json_link_watch(const ni_team_link_watch_array_t *link_watch) } } +static void +ni_teamd_config_json_notify_peers(ni_json_t *root, const ni_team_notify_peers_t *np) +{ + ni_json_t *object; + + if (np->count == -1U && np->interval == -1U) + return; + + object = ni_json_new_object(); + + if (np->count != -1U) + ni_json_object_set(object, "count", ni_json_new_int64(np->count)); + + if (np->interval != -1U) + ni_json_object_set(object, "interval", ni_json_new_int64(np->interval)); + + ni_json_object_set(root, "notify_peers", object); +} + +static void +ni_teamd_config_json_mcast_rejoin(ni_json_t *root, const ni_team_mcast_rejoin_t *mc) +{ + ni_json_t *object; + + if (mc->count == -1U && mc->interval == -1U) + return; + + object = ni_json_new_object(); + + if (mc->count != -1U) + ni_json_object_set(object, "count", ni_json_new_int64(mc->count)); + + if (mc->interval != -1U) + ni_json_object_set(object, "interval", ni_json_new_int64(mc->interval)); + + ni_json_object_set(root, "mcast_rejoin", object); +} + static int ni_teamd_config_file_dump(FILE *fp, const char *instance, const ni_team_t *config, const ni_hwaddr_t *hwaddr) { ni_stringbuf_t dump = NI_STRINGBUF_INIT_DYNAMIC; ni_json_t *object, *child; + const char *name; if (!fp || ni_string_empty(instance) || !config) return -1; @@ -1402,10 +1500,19 @@ ni_teamd_config_file_dump(FILE *fp, const char *instance, const ni_team_t *confi ni_json_object_set(object, "hwaddr", ni_json_new_string(ni_link_address_print(hwaddr))); } + if (config->debug_level > 0) + ni_json_object_set(object, "debug_level", ni_json_new_int64(config->debug_level)); + + ni_teamd_config_json_notify_peers(object, &config->notify_peers); + ni_teamd_config_json_mcast_rejoin(object, &config->mcast_rejoin); + if (!(child = ni_teamd_config_json_runner(&config->runner))) goto failure; ni_json_object_set(object, "runner", child); + if ((name = ni_team_link_watch_policy_type_to_name(config->link_watch_policy))) + ni_json_object_set(object, "link_watch_policy", ni_json_new_string(name)); + if (config->link_watch.count) { if (!(child = ni_teamd_config_json_link_watch(&config->link_watch))) goto failure; diff --git a/util/mkconst.c b/util/mkconst.c index 25d95901b..a5bedae16 100644 --- a/util/mkconst.c +++ b/util/mkconst.c @@ -98,6 +98,7 @@ static struct generic_map generic_maps[] = { MAP(TEAM_TX_BALANCER, ni_team_tx_balancer_type_to_name), MAP(TEAM_AB_HWADDR_POLICY, ni_team_ab_hwaddr_policy_type_to_name), MAP(TEAM_LACP_SELECT_POLICY, ni_team_lacp_select_policy_type_to_name), + MAP(TEAM_LINK_WATCH_POLICY, ni_team_link_watch_policy_type_to_name), MAP(GRE_FLAG_BIT, ni_gre_flag_bit_to_name), MAP(GRE_ENCAP_TYPE, ni_gre_encap_type_to_name), MAP(GRE_ENCAP_FLAG_BIT, ni_gre_encap_flag_bit_to_name),