summaryrefslogtreecommitdiff
path: root/sys/netinet/ip_carp.c
AgeCommit message (Collapse)Author
2023-04-07Select virtual address as sender if backing interface is anonymous.mlelstv
Use correct scope for IPv6.
2023-03-26Use backing device to send advertisements. Otherwise the packets originatemlelstv
from the virtual MAC address, which confuses switches.
2022-09-02Remove unnecessary inclusion of <net/netisr.h>.thorpej
2021-09-30carp: Register carp_carpdev_state to link-state change hookyamaguchi
2021-06-16if_attach and if_initialize cannot fail, don't test return valueriastradh
These were originally made failable back in 2017 when if_initialize allocated a softint in every interface for link state changes, so that it could fail gracefully instead of panicking: https://mail-index.NetBSD.org/source-changes/2017/10/23/msg089053.html However, this spawned many seldom- or never-tested error branches, which are risky to have around. And that softint in every interface has since been replaced by a single global workqueue, because link state changes require thread context but not low latency or high throughput: https://mail-index.NetBSD.org/source-changes/2020/02/06/msg113759.html So there is no longer any reason for if_initialize to fail. (The subroutine if_stats_init can't fail because percpu_alloc can't fail either.) There is a snag: the softint_establish in if_percpuq_create could fail, potentially leading to bad consequences later on trying to use the softint. This change doesn't introduce any new bugs because of the snag -- if_percpuq_attach was already broken. However, the snag can be better addressed without spawning error branches, either by using a single softint or making softints less scarce. (Separate commit will change the signatures of if_attach and if_initialize to return void, scheduled to ride whatever is the next convenient kernel bump.) Patch and testing on amd64 and evbmips64-eb by maya@; commit message soliloquy, and compile-testing on evbppc/i386/earmv7hf, by me.
2020-10-14carp: Don't set a link level address if vhid == -1roy
Link level address for carp is dervied from vhid. Until vhid is set, carp is useless, so don't give it a link level address until a vhid is set. This fixes recent test case breakage where carp was fixed to actually print the ethernet address set by default. Note that neither carp nor the test case itself was actually broken as the error is the common ATF net code assuming that a cloned interface's link level address is unique upon creation.
2020-10-12carp: link state is DOWN until it becomes a MASTERroy
This is consitent with other BSD's handling of CARP and means we don't have to carry a custom flag for it.
2020-10-12carp: Set ethernet address just before interface registationroy
Otherwise ifconfig reports SIOCGLIFADDR errors.
2020-10-09carp: Remove media, software should use link status.roy
carp literally has no media just like ppp, vlan, etc.
2020-02-06Perform link state change processing on a work queue, rather than in athorpej
softint.
2020-02-04Use ifmedia_fini().thorpej
2020-01-29Adopt <net/if_stats.h>.thorpej
2020-01-20Remove FDDI support.thorpej
2020-01-19Remove Token Ring support.thorpej
2020-01-16Provide SIOCGIFMEDIA ioctl to deliver link status.kardel
Add link0 (IFF_LINK0) flag to map INIT state to LINK_STATE_DOWN instead of LINK_STATE_UNKNOWN. This allows routing software to suppress routes to the interface of the carp interface when in init state (e. g. link down in the parent interface).
2019-11-10in many device attach paths, allocate memory with M_WAITOK instead of M_NOWAITchs
and remove code to handle failures that can no longer happen.
2019-06-01Define carp6_cksum only when it is used, that is under INET6joerg
2019-03-14carp: don't skip pserialize_read_enter and ifa_releaseozaki-r
2018-12-22Replace M_ALIGN and MH_ALIGN by m_align.maxv
2018-09-14Use non-variadic function pointer in protosw::pr_input.maxv
2018-06-26 Implement the BPF direction filter (BIOC[GS]DIRECTION). It provides backwardmsaitoh
compatibility with BIOC[GS]SEESENT ioctl. The userland interface is the same as FreeBSD. This change also fixes a bug that the direction is misunderstand on some environment by passing the direction to bpf_mtap*() instead of checking m->m_pkthdr.rcvif.
2018-06-14Add the lock to refer the list included in ethercom for safetyyamaguchi
The lock is already held while adding and deleting ok ozaki-r@
2018-06-14Use ether_lookup_multi() instead of the macroyamaguchi
ok ozaki-r@
2018-05-18IP6_EXTHDR_GET -> M_REGION_GET, no functional change.maxv
2018-03-21Fix an untriggerable memory leak. carp_prepare_ad does not fail, so switchmaxv
it to void.
2017-12-06Make if_link_queue MP-safe if IFEF_MPSAFEozaki-r
if_link_queue is a queue to store events of link state changes, which is used to pass events from (typically) an interrupt handler to if_link_state_change softint. The queue was protected by KERNEL_LOCK so far, but if IFEF_MPSAFE is enabled, it becomes unsafe because (perhaps) an interrupt handler of an interface with IFEF_MPSAFE doesn't take KERNEL_LOCK. Protect it by a spin mutex. Additionally with this change KERNEL_LOCK of if_link_state_change softint is omitted if NET_MPSAFE is enabled. Note that the spin mutex is now ifp->if_snd.ifq_lock as well as the case of if_timer (see the comment).
2017-11-22Protect IFADDR_READER_FOREACH and obtained ifa with psz/psrefozaki-r
2017-11-16Unify IFEF_*_MPSAFE into IFEF_MPSAFEozaki-r
There are already two flags for if_output and if_start, however, it seems such MPSAFE flags are eventually needed for all if_XXX operations. Having discrete flags for each operation is wasteful of if_extflags bits. So let's unify the flags into one: IFEF_MPSAFE. Fortunately IFEF_*_MPSAFE flags have never been included in any releases, so we can change them without breaking backward compatibility of the releases (though the kernel version of -current should be bumped). Note that if an interface have both MP-safe and non-MP-safe operations at a time, we have to set the IFEF_MPSAFE flag and let callees of non-MP-safe opeartions take the kernel lock. Proposed on tech-kern@ and tech-net@
2017-10-23 If if_initialize() failed in the attach function, free resources and return.msaitoh
2017-05-19Allow CARP to call the link_state_change handler immediatelyozaki-r
If the handler is delayed because of the indirection call via softint, some operations are executed in reverse and may cause unexpected behaviors. For example, due to the issue a GARP packet wasn't sent on a transition from the BACKUP state to the MASTER state; this happened because IN_IFF_DETACHED flag wasn't cleared on arpannounce, which had been cleared in the link_state_change handler. This fixes an issue reported by sborrill@ on tech-net: http://mail-index.netbsd.org/tech-net/2017/03/14/msg006283.html
2017-05-12replace in_fmtaddr() by IN_PRINT(), and delete function in_fmtaddr()ryo
2017-05-12carp should call if_link_state_change instead of affectingroy
if_link_state directly.
2017-04-19Fix build without INET6ozaki-r
2017-03-14Use if_acquire and if_release instead of using psref API directlyozaki-r
- Provide if_release for consistency to if_acquire - Use if_acquire and if_release for ifp iterations - Make ifnet_psref_class static
2017-02-27Make CARP on IPv6 workozaki-r
It passes ATF tests but no more, no less.
2017-02-02Defer some pr_input to workqueueozaki-r
pr_input is currently called in softint. Some pr_input such as ICMP, ICMPv6 and CARP can add/delete/update IP addresses and routing table entries. For example, icmp6_redirect_input updates an a routing table entry and nd6_ra_input may delete an IP address. Basically such operations shouldn't be done in softint. That aside, we have a reason to avoid the situation; psz/psref waits cannot be used in softint, however they are required to work in such pr_input in the MP-safe world. The change implements the workqueue pr_input framework called wqinput which provides a means to defer pr_input of a protocol to workqueue easily. Currently icmp_input, icmp6_input, carp_proto_input and carp6_proto_input are deferred to workqueue by the framework. Proposed and discussed on tech-kern and tech-net
2017-01-16ip6_sprintf -> IN6_PRINT so that we pass the size.christos
2017-01-16Make ip6_sprintf(), in_fmtaddr(), lla_snprintf() and icmp6_redirect_diag() ↵ryo
mpsafe. Reviewed by ozaki-r@
2016-12-28Use ether_ifattach in carp_clone_create instead of C&P codeozaki-r
carp_clone_destroy calls ether_ifdetach so not calling ether_ifattach is inconsistent. If we add something pair of initialization and destruction to ether_ifattach and ether_ifdetach (e.g., mutex_init/mutex_destroy), ether_ifdetach of carp_clone_destroy won't work. So use ether_ifattach. In order to do so, make ether_ifattach accept the 2nd argument (lla) as NULL to allow carp to initialize its link level address by itself.
2016-12-12Make the routing table and rtcaches MP-safeozaki-r
See the following descriptions for details. Proposed on tech-kern and tech-net Overview -------- We protect the routing table with a rwock and protect rtcaches with another rwlock. Each rtentry is protected from being freed or updated via reference counting and psref. Global rwlocks -------------- There are two rwlocks; one for the routing table (rt_lock) and the other for rtcaches (rtcache_lock). rtcache_lock covers all existing rtcaches; there may have room for optimizations (future work). The locking order is rtcache_lock first and rt_lock is next. rtentry references ------------------ References to an rtentry is managed with reference counting and psref. Either of the two mechanisms is used depending on where a rtentry is obtained. Reference counting is used when we obtain a rtentry from the routing table directly via rtalloc1 and rtrequest{,1} while psref is used when we obtain a rtentry from a rtcache via rtcache_* APIs. In both cases, a caller can sleep/block with holding an obtained rtentry. The reasons why we use two different mechanisms are (i) only using reference counting hurts the performance due to atomic instructions (rtcache case) (ii) ease of implementation; applying psref to APIs such rtaloc1 and rtrequest{,1} requires additional works (adding a local variable and an argument). We will finally migrate to use only psref but we can do it when we have a lockless routing table alternative. Reference counting for rtentry ------------------------------ rt_refcnt now doesn't count permanent references such as for rt_timers and rtcaches, instead it is used only for temporal references when obtaining a rtentry via rtalloc1 and rtrequest{,1}. We can do so because destroying a rtentry always involves removing references of rt_timers and rtcaches to the rtentry and we don't need to track such references. This also makes it easy to wait for readers to release references on deleting or updating a rtentry, i.e., we can simply wait until the reference counter is 0 or 1. (If there are permanent references the counter can be arbitrary.) rt_ref increments a reference counter of a rtentry and rt_unref decrements it. rt_ref is called inside APIs (rtalloc1 and rtrequest{,1} so users don't need to care about it while users must call rt_unref to an obtained rtentry after using it. rtfree is removed and we use rt_unref and rt_free instead. rt_unref now just decrements the counter of a given rtentry and rt_free just tries to destroy a given rtentry. See the next section for destructions of rtentries by rt_free. Destructions of rtentries ------------------------- We destroy a rtentry only when we call rtrequst{,1}(RTM_DELETE); the original implementation can destroy in any rtfree where it's the last reference. If we use reference counting or psref, it's easy to understand if the place that a rtentry is destroyed is fixed. rt_free waits for references to a given rtentry to be released before actually destroying the rtentry. rt_free uses a condition variable (cv_wait) (and psref_target_destroy for psref) to wait. Unfortunately rtrequst{,1}(RTM_DELETE) can be called in softint that we cannot use cv_wait. In that case, we have to defer the destruction to a workqueue. rtentry#rt_cv, rtentry#rt_psref and global variables (see rt_free_global) are added to conduct the procedure. Updates of rtentries -------------------- One difficulty to use refcnt/psref instead of rwlock for rtentry is updates of rtentries. We need an additional mechanism to prevent readers from seeing inconsistency of a rtentry being updated. We introduce RTF_UPDATING flag to rtentries that are updating. While the flag is set to a rtentry, users cannot acquire the rtentry. By doing so, we avoid users to see inconsistent rtentries. There are two options when a user tries to acquire a rtentry with the RTF_UPDATING flag; if a user runs in softint context the user fails to acquire a rtentry (NULL is returned). Otherwise a user waits until the update completes by waiting on cv. The procedure of a updater is simpler to destruction of a rtentry. Wait on cv (and psref) and after all readers left, proceed with the update. Global variables (see rt_update_global) are added to conduct the procedure. Currently we apply the mechanism to only RTM_CHANGE in rtsock.c. We would have to apply other codes. See "Known issues" section. psref for rtentry ----------------- When we obtain a rtentry from a rtcache via rtcache_* APIs, psref is used to reference to the rtentry. rtcache_ref acquires a reference to a rtentry with psref and rtcache_unref releases the reference after using it. rtcache_ref is called inside rtcache_* APIs and users don't need to take care of it while users must call rtcache_unref to release the reference. struct psref and int bound that is needed for psref is embedded into struct route. By doing so we don't need to add local variables and additional argument to APIs. However this adds another constraint to psref other than reference counting one's; holding a reference of an rtentry via a rtcache is allowed by just one caller at the same time. So we must not acquire a rtentry via a rtcache twice and avoid a recursive use of a rtcache. And also a rtcache must be arranged to be used by a LWP/softint at the same time somehow. For IP forwarding case, we have per-CPU rtcaches used in softint so the constraint is guaranteed. For a h rtcache of a PCB case, the constraint is guaranteed by the solock of each PCB. Any other cases (pf, ipf, stf and ipsec) are currently guaranteed by only the existence of the global locks (softnet_lock and/or KERNEL_LOCK). If we've found the cases that we cannot guarantee the constraint, we would need to introduce other rtcache APIs that use simple reference counting. psref of rtcache is created with IPL_SOFTNET and so rtcache shouldn't used at an IPL higher than IPL_SOFTNET. Note that rtcache_free is used to invalidate a given rtcache. We don't need another care by my change; just keep them as they are. Performance impact ------------------ When NET_MPSAFE is disabled the performance drop is 3% while when it's enabled the drop is increased to 11%. The difference comes from that currently we don't take any global locks and don't use psref if NET_MPSAFE is disabled. We can optimize the performance of the case of NET_MPSAFE on by reducing lookups of rtcache that uses psref; currently we do two lookups but we should be able to trim one of two. This is a future work. Known issues ------------ There are two known issues to be solved; one is that a caller of rtrequest(RTM_ADD) may change rtentry (see rtinit). We need to prevent new references during the update. Or we may be able to remove the code (perhaps, need more investigations). The other is rtredirect that updates a rtentry. We need to apply our update mechanism, however it's not easy because rtredirect is called in softint and we cannot apply our mechanism simply. One solution is to defer rtredirect to a workqueue but it requires some code restructuring.
2016-10-11Remove unused variable.roy
2016-10-11Mark arprequest static and introduce arpannounce so that gratuitousroy
ARP requests are only send from valid addresses.
2016-08-01Apply pserialize and psref to struct ifaddr and its variantsozaki-r
This change makes struct ifaddr and its variants (in_ifaddr and in6_ifaddr) MP-safe by using pserialize and psref. At this moment, pserialize_perform and psref_target_destroy are disabled because (1) we don't need them because of softnet_lock (2) they cause a deadlock because of softnet_lock. So we'll enable them when we remove softnet_lock in the future.
2016-07-23Print the IPv6 or IPv4 source addresses of packets with wrong hash, tois
help debugging.
2016-07-23Workaround for PR 47013 by bouyer@. Only works for mixed IPv4/IPv6is
environemnts, not for pure-IPv6 yet. A real fix is still needed.
2016-07-07Switch the address list of intefaces to pslist(9)ozaki-r
As usual, we leave the old list to avoid breaking kvm(3) users.
2016-07-06Switch the IPv4 address list to pslist(9)ozaki-r
Note that we leave the old list just in case; it seems there are some kvm(3) users accessing the list. We can remove it later if we confirmed nobody does actually.
2016-07-04Use pslist(9) for the global in6_ifaddr listozaki-r
psz and psref will be applied in another commit. No functional change intended.
2016-06-21Replace ifp of ip_moptions and ip6_moptions with if_indexozaki-r
The motivation is the same as the mbuf's rcvif case; avoid having a pointer of an ifnet object in ip_moptions and ip6_moptions, which is not MP-safe. ip_moptions and ip6_moptions can be stored in a PCB for inet or inet6 that's life time is different from ifnet one and so an ifnet object can be disappeared anytime we get it via them. Thus we need to look up an ifnet object by if_index every time for safe.
2016-06-20fix: i386/ALL build failureknakahara