Re: ospf6d: configured "type p2p" is lost on RTM_IFINFO (interface flap)
Atanas Vladimirov <[email protected]> Fri, 24 Jul 2026 11:33:20 +0300
| Newsgroups | gmane.os.openbsd.bugs |
|---|---|
| Message-ID | <[email protected]> |
On 2026-07-22 09:47, Atanas Vladimirov wrote: > On 2026-07-22 08:13, Bjorn Ketelaars wrote: >> On Tue 21/07/2026 19:14, Atanas Vladimirov wrote: >>> > Synopsis: ospf6d forgets configured "type p2p" when the interface >>> generates an RTM_IFINFO message (e.g. ifconfig down/up) >>> > Category: user >>> > Environment: >>> System : OpenBSD -current (8.0-beta) >>> Details : OpenBSD 8.0-beta (GENERIC.MP) #45: Sat Jul 18 >>> 11:29:43 >>> MDT 2026 >>> [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP >>> >>> Architecture: OpenBSD.amd64 >>> Machine : amd64 >>> >>> > Description: >>> An interface configured with "type p2p" in ospf6d.conf silently >>> reverts to network type BROADCAST as soon as any RTM_IFINFO >>> message arrives for that interface (for example after >>> "ifconfig <if> down" / "ifconfig <if> up", or any other flags >>> change). The daemon then starts DR election on the link. If the >>> remote router keeps running the link as point-to-point, both >>> sides can still reach neighbor state FULL, but SPF discards the >>> link because the router-LSAs describe it inconsistently >>> (p2p link on one side, transit network plus network-LSA on the >>> other), so no routes are computed across it. >>> >>> This is particularly easy to hit with wg(4) interfaces, which >>> advertise IFF_BROADCAST|IFF_MULTICAST (sys/net/if_wg.c): >>> >>> ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_NOARP; >>> >>> Root cause: if_update() in usr.sbin/ospf6d/interface.c >>> unconditionally re-derives iface->type from the kernel interface >>> flags every time it is called: >>> >>> /* set type */ >>> if (flags & IFF_POINTOPOINT) >>> iface->type = IF_TYPE_POINTOPOINT; >>> if (flags & IFF_BROADCAST && flags & IFF_MULTICAST) >>> iface->type = IF_TYPE_BROADCAST; >>> >>> At startup this is masked: ospf6d.c calls if_init() first and >>> parse_config() afterwards, so the "type p2p" override from >>> parse.y wins. But the configured value is not remembered >>> anywhere. When an RTM_IFINFO arrives, the dispatch chain >>> kroute.c:if_change() -> kif_update() -> if_update() resets the >>> type to BROADCAST in the parent process, and the IMSG_IFINFO >>> handlers in ospfe.c and rde.c call if_update() again on their >>> own copies, resetting it there too. From that point on the >>> interface runs as broadcast until the daemon is restarted and >>> the config is re-applied. >>> >>> ospfd (IPv4) does not have this problem, which makes the >>> asymmetry very visible when both daemons run over the same >>> tunnel: ospfd keeps kernel interface state in a separate >>> struct kif, derives iface->type only once when the iface is >>> created from config (interface.c:if_new()), and its IMSG_IFINFO >>> handler only copies flags/linkstate/mtu, never the type. >>> >>> > How-To-Repeat: >>> 1. Configure an interface with "type p2p" in ospf6d.conf. >>> A wg(4) interface makes the bug visible because its flags >>> include IFF_BROADCAST|IFF_MULTICAST, but any interface whose >>> flags would not derive to POINTOPOINT works. >>> >>> area 0.0.0.0 { >>> interface wg0 { type p2p } >>> } >>> >>> 2. Start ospf6d and verify: >>> # ospf6ctl show interface wg0 | grep 'network type' >>> -> network type POINTOPOINT >>> 3. Generate an RTM_IFINFO for the interface: >>> # ifconfig wg0 down; ifconfig wg0 up >>> 4. Check again: >>> # ospf6ctl show interface wg0 | grep 'network type' >>> -> network type BROADCAST, DR election in progress. >>> 5. rcctl restart ospf6d restores POINTOPOINT (until the next >>> flap). >>> >>> > Fix: >>> I don't know. >>> >>> OpenBSD 8.0-beta (GENERIC.MP) #45: Sat Jul 18 11:29:43 MDT 2026 >>> >>> [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP >>> real mem = 34154913792 (32572MB) >>> avail mem = 33093713920 (31560MB) >>> random: good seed from bootblocks >>> mpath0 at root >>> scsibus0 at mpath0: 256 targets >>> mainbus0 at root >>> bios0 at mainbus0: SMBIOS rev. 3.0 @ 0x7fb76000 (62 entries) >>> bios0: vendor American Megatrends Inc. version "3.6" date 04/25/2025 >>> bios0: Supermicro Super Server >>> efi0 at bios0: UEFI 2.4 >>> efi0: American Megatrends rev 0x5000b >>> acpi0 at bios0: ACPI 5.0 >>> acpi0: sleep states S0 S4 S5 >>> acpi0: tables DSDT FACP APIC FPDT FIDT SPMI SLIC MCFG HPET LPIT SSDT >>> SSDT >>> SSDT DBGP DBG2 SSDT SSDT UEFI SSDT DMAR BGRT EINJ ERST BERT HEST >>> acpi0: wakeup devices PEG0(S4) PEGP(S4) PEG1(S4) PEGP(S4) PEG2(S4) >>> PEGP(S4) >>> RP09(S4) PXSX(S4) RP10(S4) PXSX(S4) RP11(S4) PXSX(S4) RP12(S4) >>> PXSX(S4) >>> RP13(S4) PXSX(S4) [...] >>> acpitimer0 at acpi0: 3579545 Hz, 24 bits >>> acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat >>> cpu0 at mainbus0: apid 0 (boot processor) >>> cpu0: Intel(R) Xeon(R) CPU E3-1220 v6 @ 3.00GHz, 3000.00 MHz, >>> 06-9e-09, >>> patch 000000fa >>> cpu0: cpuid 1 >>> edx=bfebfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE> >>> ecx=77fafbff<SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,SMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND> >>> cpu0: cpuid 6 eax=27f7<SENSOR,ARAT,PTS> ecx=9<EFFFREQ> >>> cpu0: cpuid 7.0 >>> ebx=29c6fbf<FSGSBASE,TSC_ADJUST,SGX,BMI1,HLE,AVX2,SMEP,BMI2,ERMS,INVPCID,RTM,MPX,RDSEED,ADX,SMAP,CLFLUSHOPT,PT> >>> edx=bc002e00<SRBDS_CTRL,MD_CLEAR,TSXFA,IBRS,IBPB,STIBP,L1DF,SSBD> >>> cpu0: cpuid a vers=4, gp=8, gpwidth=48, ff=3, ffwidth=48 >>> cpu0: cpuid d.1 eax=f<XSAVEOPT,XSAVEC,XGETBV1,XSAVES> >>> cpu0: cpuid 80000001 edx=2c100800<NXE,PAGE1GB,RDTSCP,LONG> >>> ecx=121<LAHF,ABM,3DNOWP> >>> cpu0: cpuid 80000007 edx=100<ITSC> >>> cpu0: msr 10a=a000c04<RSBA,MISC_PKG_CT,ENERGY_FILT,GDS_CTRL,RFDS_NO> >>> cpu0: MELTDOWN >>> cpu0: 32KB 64b/line 8-way D-cache, 32KB 64b/line 8-way I-cache, 256KB >>> 64b/line 4-way L2 cache, 8MB 64b/line 16-way L3 cache >>> cpu0: smt 0, core 0, package 0, type P >>> mtrr: Pentium Pro MTRR support, 10 var ranges, 88 fixed ranges >>> cpu0: apic clock running at 24MHz >>> cpu0: mwait min=64, max=64, C-substates=0.2.1.2.4.1, IBE >>> cpu1 at mainbus0: apid 2 (application processor) >>> cpu1: Intel(R) Xeon(R) CPU E3-1220 v6 @ 3.00GHz, 3000.00 MHz, >>> 06-9e-09, >>> patch 000000fa >>> cpu1: smt 0, core 1, package 0, type P >>> cpu2 at mainbus0: apid 4 (application processor) >>> cpu2: Intel(R) Xeon(R) CPU E3-1220 v6 @ 3.00GHz, 3000.00 MHz, >>> 06-9e-09, >>> patch 000000fa >>> cpu2: smt 0, core 2, package 0, type P >>> cpu3 at mainbus0: apid 6 (application processor) >>> cpu3: Intel(R) Xeon(R) CPU E3-1220 v6 @ 3.00GHz, 3000.00 MHz, >>> 06-9e-09, >>> patch 000000fa >>> cpu3: smt 0, core 3, package 0, type P >>> ioapic0 at mainbus0: apid 2 pa 0xfec00000, version 20, 24 pins >>> acpimcfg0 at acpi0 >>> acpimcfg0: addr 0xe0000000, bus 0-255 >>> acpihpet0 at acpi0: 23999999 Hz >>> acpiprt0 at acpi0: bus 0 (PCI0) >>> acpiprt1 at acpi0: bus 1 (PEG0) >>> acpiprt2 at acpi0: bus 2 (PEG1) >>> acpiprt3 at acpi0: bus -1 (PEG2) >>> acpiprt4 at acpi0: bus 6 (RP09) >>> acpiprt5 at acpi0: bus 7 (RP10) >>> acpiprt6 at acpi0: bus 8 (RP11) >>> acpiprt7 at acpi0: bus 9 (BR51) >>> acpiprt8 at acpi0: bus -1 (RP12) >>> acpiprt9 at acpi0: bus -1 (RP13) >>> acpiprt10 at acpi0: bus -1 (RP01) >>> acpiprt11 at acpi0: bus -1 (RP05) >>> acpiprt12 at acpi0: bus -1 (RP17) >>> acpiprt13 at acpi0: bus -1 (RP18) >>> acpiprt14 at acpi0: bus -1 (RP19) >>> acpiprt15 at acpi0: bus -1 (RP20) >>> acpiprt16 at acpi0: bus -1 (RP14) >>> acpiprt17 at acpi0: bus -1 (RP15) >>> acpiprt18 at acpi0: bus -1 (RP16) >>> acpiec0 at acpi0: not present >>> acpipci0 at acpi0 PCI0: 0x00000000 0x00000011 0x00000001 >>> com0 at acpi0 UAR1 addr 0x3f8/0x8 irq 4: ns16550a, 16 byte fifo >>> com1 at acpi0 UAR2 addr 0x2f8/0x8 irq 3: ns16550a, 16 byte fifo >>> com1: console >>> acpicmos0 at acpi0 >>> "IPI0001" at acpi0 not configured >>> "INT0E0C" at acpi0 not configured >>> acpibtn0 at acpi0: SLPB >>> intelpmc0 at acpi0: PEPD >>> state 0: 0x7f:1:2:0x00:0x0000000000000060 >>> counter: 0x7f:64:0:0x00:0x0000000000000632 >>> frequency: 0 >>> state 1: 0x7f:1:2:0x00:0x0000000000000060 >>> counter: 0x7f:64:0:0x00:0x0000000000000632 >>> frequency: 0 >>> acpibtn1 at acpi0: PWRB >>> "PNP0C0B" at acpi0 not configured >>> "PNP0C0B" at acpi0 not configured >>> "PNP0C0B" at acpi0 not configured >>> "PNP0C0B" at acpi0 not configured >>> "PNP0C0B" at acpi0 not configured >>> acpicpu0 at acpi0: C3(200@256 mwait.1@0x40), C2(200@151 >>> mwait.1@0x33), >>> C1(1000@1 mwait.1), PSS >>> acpicpu1 at acpi0: C3(200@256 mwait.1@0x40), C2(200@151 >>> mwait.1@0x33), >>> C1(1000@1 mwait.1), PSS >>> acpicpu2 at acpi0: C3(200@256 mwait.1@0x40), C2(200@151 >>> mwait.1@0x33), >>> C1(1000@1 mwait.1), PSS >>> acpicpu3 at acpi0: C3(200@256 mwait.1@0x40), C2(200@151 >>> mwait.1@0x33), >>> C1(1000@1 mwait.1), PSS >>> acpipwrres0 at acpi0: PG00, resource for PEG0 >>> acpipwrres1 at acpi0: PG01, resource for PEG1 >>> acpipwrres2 at acpi0: PG02, resource for PEG2 >>> acpipwrres3 at acpi0: WRST >>> acpipwrres4 at acpi0: WRST >>> acpipwrres5 at acpi0: WRST >>> acpipwrres6 at acpi0: WRST >>> acpipwrres7 at acpi0: WRST >>> acpipwrres8 at acpi0: WRST >>> acpipwrres9 at acpi0: WRST >>> acpipwrres10 at acpi0: WRST >>> acpipwrres11 at acpi0: WRST >>> acpipwrres12 at acpi0: WRST >>> acpipwrres13 at acpi0: WRST >>> acpipwrres14 at acpi0: WRST >>> acpipwrres15 at acpi0: WRST >>> acpipwrres16 at acpi0: WRST >>> acpipwrres17 at acpi0: WRST >>> acpipwrres18 at acpi0: WRST >>> acpipwrres19 at acpi0: WRST >>> acpipwrres20 at acpi0: WRST >>> acpipwrres21 at acpi0: WRST >>> acpipwrres22 at acpi0: WRST >>> acpipwrres23 at acpi0: FN00, resource for FAN0 >>> acpipwrres24 at acpi0: FN01, resource for FAN1 >>> acpipwrres25 at acpi0: FN02, resource for FAN2 >>> acpipwrres26 at acpi0: FN03, resource for FAN3 >>> acpipwrres27 at acpi0: FN04, resource for FAN4 >>> acpitz0 at acpi0 >>> acpitz0: critical temperature is 119 degC >>> acpitz1 at acpi0 >>> acpitz1: critical temperature is 119 degC >>> acpivideo0 at acpi0: GFX0 >>> acpivout0 at acpivideo0: DD1F >>> ipmi at mainbus0 not configured >>> cpu0: using VERW MDS workaround (except on vmm entry) >>> cpu0: Enhanced SpeedStep 3000 MHz: speeds: 3001, 3000, 2800, 2700, >>> 2500, >>> 2400, 2200, 2100, 1900, 1700, 1600, 1400, 1300, 1100, 1000, 800 MHz >>> pci0 at mainbus0 bus 0 >>> pchb0 at pci0 dev 0 function 0 "Intel Xeon E3-1200 v6/7 Host" rev >>> 0x05 >>> ppb0 at pci0 dev 1 function 0 "Intel Core 6G PCIE" rev 0x05: msi >>> pci1 at ppb0 bus 1 >>> ix0 at pci1 dev 0 function 0 "Intel 82599" rev 0x01, msix, 4 queues, >>> address >>> 90:e2:ba:f3:2e:1c >>> ix1 at pci1 dev 0 function 1 "Intel 82599" rev 0x01, msix, 4 queues, >>> address >>> 90:e2:ba:f3:2e:1d >>> ppb1 at pci0 dev 1 function 1 "Intel Core 6G PCIE" rev 0x05: msi >>> pci2 at ppb1 bus 2 >>> ppb2 at pci2 dev 0 function 0 "IDT 89HPES12N3A" rev 0x0e >>> pci3 at ppb2 bus 3 >>> ppb3 at pci3 dev 2 function 0 "IDT 89HPES12N3A" rev 0x0e >>> pci4 at ppb3 bus 4 >>> em0 at pci4 dev 0 function 0 "Intel 82571EB" rev 0x06: apic 2 int 16, >>> address 00:15:17:bc:a9:65 >>> em1 at pci4 dev 0 function 1 "Intel 82571EB" rev 0x06: apic 2 int 19, >>> address 00:15:17:bc:a9:64 >>> ppb4 at pci3 dev 4 function 0 "IDT 89HPES12N3A" rev 0x0e >>> pci5 at ppb4 bus 5 >>> em2 at pci5 dev 0 function 0 "Intel 82571EB" rev 0x06: apic 2 int 18, >>> address 00:15:17:bc:a9:67 >>> em3 at pci5 dev 0 function 1 "Intel 82571EB" rev 0x06: apic 2 int 17, >>> address 00:15:17:bc:a9:66 >>> "Intel 100 Series ISH" rev 0x31 at pci0 dev 19 function 0 not >>> configured >>> xhci0 at pci0 dev 20 function 0 "Intel 100 Series xHCI" rev 0x31: >>> msi, xHCI >>> 1.0 >>> usb0 at xhci0: USB revision 3.0 >>> uhub0 at usb0 configuration 1 interface 0 "Intel xHCI root hub" rev >>> 3.00/1.00 addr 1 >>> pchtemp0 at pci0 dev 20 function 2 "Intel 100 Series Thermal" rev >>> 0x31 >>> "Intel 100 Series MEI" rev 0x31 at pci0 dev 22 function 0 not >>> configured >>> ahci0 at pci0 dev 23 function 0 "Intel 100 Series AHCI" rev 0x31: >>> msi, AHCI >>> 1.3.1 >>> ahci0: port 0: 6.0Gb/s >>> ahci0: port 1: 6.0Gb/s >>> scsibus1 at ahci0: 32 targets >>> sd0 at scsibus1 targ 0 lun 0: <ATA, SAMSUNG MZ7L33T8, JXTC> >>> naa.5002538f02212827 >>> sd0: 3662830MB, 512 bytes/sector, 7501476528 sectors, thin >>> sd1 at scsibus1 targ 1 lun 0: <ATA, SAMSUNG MZ7LM3T8, GXT5> >>> naa.5002538c407c5ab3 >>> sd1: 3662830MB, 512 bytes/sector, 7501476528 sectors, thin >>> ppb5 at pci0 dev 29 function 0 "Intel 100 Series PCIE" rev 0xf1: msi >>> pci6 at ppb5 bus 6 >>> em4 at pci6 dev 0 function 0 "Intel I210" rev 0x03: msi, address >>> ac:1f:6b:96:83:30 >>> ppb6 at pci0 dev 29 function 1 "Intel 100 Series PCIE" rev 0xf1: msi >>> pci7 at ppb6 bus 7 >>> em5 at pci7 dev 0 function 0 "Intel I210" rev 0x03: msi, address >>> ac:1f:6b:96:83:31 >>> ppb7 at pci0 dev 29 function 2 "Intel 100 Series PCIE" rev 0xf1: msi >>> pci8 at ppb7 bus 8 >>> ppb8 at pci8 dev 0 function 0 "ASPEED Technology AST1150 PCI" rev >>> 0x03 >>> pci9 at ppb8 bus 9 >>> "ASPEED Technology AST2000" rev 0x30 at pci9 dev 0 function 0 not >>> configured >>> pcib0 at pci0 dev 31 function 0 "Intel C232 LPC" rev 0x31 >>> "Intel 100 Series PMC" rev 0x31 at pci0 dev 31 function 2 not >>> configured >>> ichiic0 at pci0 dev 31 function 4 "Intel 100 Series SMBus" rev 0x31: >>> apic 2 >>> int 16 >>> iic0 at ichiic0 >>> iic0: addr 0x19 00=00 01=00 02=04 03=00 04=06 05=02 06=1c 07=22 08=00 >>> words >>> 00=00ef 01=000d 02=04b0 03=0000 04=0610 05=026c 06=1c85 07=2221 >>> iic0: addr 0x1b 00=00 01=00 02=04 03=00 04=06 05=02 06=1c 07=22 08=00 >>> words >>> 00=00ef 01=000d 02=04b0 03=0000 04=0610 05=0268 06=1c85 07=2221 >>> spdmem0 at iic0 addr 0x51: 16GB DDR4 SDRAM ECC PC4-25600 with thermal >>> sensor >>> spdmem1 at iic0 addr 0x53: 16GB DDR4 SDRAM ECC PC4-25600 with thermal >>> sensor >>> isa0 at pcib0 >>> isadma0 at isa0 >>> pcppi0 at isa0 port 0x61 >>> spkr0 at pcppi0 >>> vmm0 at mainbus0: VMX/EPT >>> efifb0 at mainbus0: 1024x768, 32bpp >>> wsdisplay0 at efifb0 mux 1 >>> wsdisplay0: screen 0-5 added (std, vt100 emulation) >>> enable mbufs in high memory >>> uplcom0 at uhub0 port 6 configuration 1 interface 0 "Prolific >>> Technology >>> Inc. USB-Serial Controller" rev 1.10/3.00 addr 2 >>> ucom0 at uplcom0: usb0.0.00006.0 >>> uhidev0 at uhub0 port 8 configuration 1 interface 0 "Logitech USB >>> Receiver" >>> rev 2.00/29.00 addr 3 >>> uhidev0: iclass 3/1 >>> ukbd0 at uhidev0: 8 variable keys, 6 key codes >>> wskbd0 at ukbd0 mux 1 >>> wskbd0: connecting to wsdisplay0 >>> uhidev1 at uhub0 port 8 configuration 1 interface 1 "Logitech USB >>> Receiver" >>> rev 2.00/29.00 addr 3 >>> uhidev1: iclass 3/1, 17 report ids >>> uhidpp0 at uhidev1 device 1 keyboard " ", device 2 mouse "" >>> ums0 at uhidev1 reportid 2: 16 buttons, Z and W dir >>> wsmouse0 at ums0 mux 0 >>> ucc0 at uhidev1 reportid 3: 652 usages, 20 keys, array >>> wskbd1 at ucc0 mux 1 >>> wskbd1: connecting to wsdisplay0 >>> uhid0 at uhidev1 reportid 4: input=1, output=0, feature=0 >>> uhub1 at uhub0 port 9 configuration 1 interface 0 "ATEN International >>> product 0x7000" rev 2.00/0.00 addr 4 >>> uhidev2 at uhub1 port 1 configuration 1 interface 0 "ATEN >>> International >>> product 0x2419" rev 1.10/1.00 addr 5 >>> uhidev2: iclass 3/1 >>> ukbd1 at uhidev2: 8 variable keys, 6 key codes >>> wskbd2 at ukbd1 mux 1 >>> wskbd2: connecting to wsdisplay0 >>> uhidev3 at uhub1 port 1 configuration 1 interface 1 "ATEN >>> International >>> product 0x2419" rev 1.10/1.00 addr 5 >>> uhidev3: iclass 3/1 >>> ums1 at uhidev3: 3 buttons, Z dir >>> wsmouse1 at ums1 mux 0 >>> vscsi0 at root >>> scsibus2 at vscsi0: 256 targets >>> softraid0 at root >>> scsibus3 at softraid0: 256 targets >>> sd2 at scsibus3 targ 1 lun 0: <OPENBSD, SR RAID 1, 006> >>> sd2: 953869MB, 512 bytes/sector, 1953524576 sectors >>> sd3 at scsibus3 targ 2 lun 0: <OPENBSD, SR RAID 1, 006> >>> sd3: 953869MB, 512 bytes/sector, 1953524576 sectors >>> sd4 at scsibus3 targ 3 lun 0: <OPENBSD, SR RAID 1, 006> >>> sd4: 915714MB, 512 bytes/sector, 1875383423 sectors >>> root on sd4a (22c9e9d08ea8ad79.a) swap on sd4b dump on sd4b >>> >> >> I could reproduce where an interface configured with type p2p in >> ospf6d.conf reverts back to BROADCAST after a link bounce. >> >> When an interface receives a link update (RTM_IFINFO), if_update() >> unconditionally re-derives iface->type from interface flags >> (IFF_POINTOPOINT, IFF_BROADCAST), overwriting the explicit >> configuration >> set during parsing. >> >> Diff below introduces F_IFACE_TYPE in cflags to track when an >> interface >> type was set by configuration, and only auto-derive the type from >> interface flags when F_IFACE_TYPE is not set. >> >> I am far from an expert here, so any feedback is appreciated. >> > > Thanks for your reply and for the patch. > I just tested it and can confirm that it works as it should :) JFTR, it was merged in https://marc.info/?l=openbsd-cvs&m=178473820339781&w=2 Thanks!