diff options
author | Felix Fietkau <nbd@nbd.name> | 2021-09-02 20:26:33 +0200 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2021-09-03 14:16:11 +0200 |
commit | 5ba9744aac6d42da1e56357aca951b52f86cfacb (patch) | |
tree | 0ae045f0f4d9d4bb5abe484b826c3b74ec34232f /system-linux.c | |
parent | 300b1220fab38600f102bb8cfcc59a29ce41b095 (diff) | |
download | netifd-5ba9744aac6d42da1e56357aca951b52f86cfacb.tar.gz |
device: add support for configuring bonding devices
Supported options:
- ports: member devices
- policy: bonding policy
supported values:
- balance-rr
- active-backup
- balance-xor
- broadcast
- 802.3ad
- balance-tlb
- balance-alb
- xmit_hash_policy: slave selection tx hash policy
supported values:
- layer2
- layer2+3
- layer3+4
- encap2+3
- encap3+4
- all_ports_active: allow receiving on inactive ports
- min_links: minimum number of active links
- ad_actor_system: LACPDU exchange MAC address
- ad_actor_sys_prio: LACPDU priority value
- ad_select: 802.3ad aggregation logic
supported values:
- stable
- bandwidth
- count
- lacp_rate: 802.3ad LACPDU packet rate
supported values:
- slow (every 30 seconds)
- fast (every second)
- packets_per_port: number of packets before switching
ports (balance-rr mode).
- lp_interval: number of seconds between sent learning packets
- dynamic_lb: distribute traffic according to port load
- resend_igmp: number if IGMP membership updates after failover event
- num_peer_notif: number of tx unsolicited ARP/NA after failover event
- primary: name of the primary port
- primary_reselect: primary port reselection policy
supported values:
- always
- better
- failure
- failover_mac: MAC address selection policy
supported values:
- none
- active
- follow
- monitor_mode: select ARP or MII link monitor:
supported values:
- arp
- mii
- monitor_interval: link monitor update interval (msec)
- arp_target: ARP monitor target IP address (list)
- arp_all_targets: all targets must be reachable to consider the link valid
- arp_validate: ARP validation policy
supported values:
- none
- active
- backup
- all
- filter
- filter_active
- filter_backup
- use_carrier: use carrier status instead of MII ioctl result
- updelay: delay before enabling port after MII link up event (msec)
- downdelay: delay before disabling port after MII link down event (msec)
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'system-linux.c')
-rw-r--r-- | system-linux.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/system-linux.c b/system-linux.c index 6c6f1ec..62038d7 100644 --- a/system-linux.c +++ b/system-linux.c @@ -350,9 +350,21 @@ system_get_dev_sysctl(const char *prefix, const char *file, const char *ifname, static void system_set_dev_sysfs(const char *file, const char *ifname, const char *val) { + if (!val) + return; + write_file(dev_sysfs_path(ifname, file), val); } +static void +system_set_dev_sysfs_int(const char *file, const char *ifname, int val) +{ + char buf[16]; + + snprintf(buf, sizeof(buf), "%d", val); + system_set_dev_sysfs(file, ifname, buf); +} + static int system_get_dev_sysfs(const char *file, const char *ifname, char *buf, size_t buf_sz) { @@ -991,6 +1003,91 @@ failure: return ret; } +int system_bonding_set_device(struct device *dev, struct bonding_config *cfg) +{ + const char *ifname = dev->ifname; + struct blob_attr *cur; + char op = cfg ? '+' : '-'; + char buf[64]; + int rem; + + snprintf(dev_buf, sizeof(dev_buf), "%s/class/net/bonding_masters", sysfs_path); + snprintf(buf, sizeof(buf), "%c%s", op, ifname); + write_file(dev_buf, buf); + + if (!cfg) + return 0; + + system_set_dev_sysfs("bonding/mode", ifname, bonding_policy_str[cfg->policy]); + + system_set_dev_sysfs_int("bonding/all_ports_active", ifname, cfg->all_ports_active); + + if (cfg->policy == BONDING_MODE_BALANCE_XOR || + cfg->policy == BONDING_MODE_BALANCE_TLB || + cfg->policy == BONDING_MODE_8023AD) + system_set_dev_sysfs("bonding/xmit_hash_policy", ifname, cfg->xmit_hash_policy); + + if (cfg->policy == BONDING_MODE_8023AD) { + system_set_dev_sysfs("bonding/ad_actor_system", ifname, cfg->ad_actor_system); + system_set_dev_sysfs_int("bonding/ad_actor_sys_prio", ifname, cfg->ad_actor_sys_prio); + system_set_dev_sysfs("bonding/ad_select", ifname, cfg->ad_select); + system_set_dev_sysfs("bonding/lacp_rate", ifname, cfg->lacp_rate); + system_set_dev_sysfs_int("bonding/min_links", ifname, cfg->min_links); + } + + if (cfg->policy == BONDING_MODE_BALANCE_RR) + system_set_dev_sysfs_int("bonding/packets_per_slave", ifname, cfg->packets_per_port); + + if (cfg->policy == BONDING_MODE_BALANCE_TLB || + cfg->policy == BONDING_MODE_BALANCE_ALB) + system_set_dev_sysfs_int("bonding/lp_interval", ifname, cfg->lp_interval); + + if (cfg->policy == BONDING_MODE_BALANCE_TLB) + system_set_dev_sysfs_int("bonding/tlb_dynamic_lb", ifname, cfg->dynamic_lb); + system_set_dev_sysfs_int("bonding/resend_igmp", ifname, cfg->resend_igmp); + system_set_dev_sysfs_int("bonding/num_grat_arp", ifname, cfg->num_peer_notif); + system_set_dev_sysfs("bonding/primary_reselect", ifname, cfg->primary_reselect); + system_set_dev_sysfs("bonding/fail_over_mac", ifname, cfg->failover_mac); + + system_set_dev_sysfs_int((cfg->monitor_arp ? + "bonding/arp_interval" : + "bonding/miimon"), ifname, cfg->monitor_interval); + + blobmsg_for_each_attr(cur, cfg->arp_target, rem) { + snprintf(buf, sizeof(buf), "+%s", blobmsg_get_string(cur)); + system_set_dev_sysfs("bonding/arp_ip_target", ifname, buf); + } + + system_set_dev_sysfs_int("bonding/arp_all_targets", ifname, cfg->arp_all_targets); + if (cfg->policy < BONDING_MODE_8023AD) + system_set_dev_sysfs("bonding/arp_validate", ifname, cfg->arp_validate); + system_set_dev_sysfs_int("bonding/use_carrier", ifname, cfg->use_carrier); + if (!cfg->monitor_arp && cfg->monitor_interval) { + system_set_dev_sysfs_int("bonding/updelay", ifname, cfg->updelay); + system_set_dev_sysfs_int("bonding/downdelay", ifname, cfg->downdelay); + } + + return 0; +} + +int system_bonding_set_port(struct device *dev, struct device *port, bool add, bool primary) +{ + const char *port_name = port->ifname; + const char op_ch = add ? '+' : '-'; + char buf[IFNAMSIZ + 2]; + + snprintf(buf, sizeof(buf), "%c%s", op_ch, port_name); + system_if_down(port); + system_set_dev_sysfs("bonding/slaves", dev->ifname, buf); + system_if_up(port); + + if (primary) + system_set_dev_sysfs("bonding/primary", dev->ifname, + add ? port_name : ""); + + return 0; +} + int system_if_resolve(struct device *dev) { struct ifreq ifr; |