From: "Sven F." Subject: Re: Pflow and Rdomain To: tech@openbsd.org Date: Tue, 10 Mar 2026 11:13:06 -0400 On Tue, Mar 10, 2026 at 9:49 AM Sven F. wrote: > Hello OpenBSD team, > > I was poking around pflow and rdomains , and i was trying to > "misuse" flowsrc, interesting part after, > > When I run: > > sh /etc/netstart pflow2 > > I receive the following errors: > > ifconfig: pflow2: SIOCSETPFLOW: Can't assign requested address > ifconfig: pflow2: SIOCSETPFLOW: Can't assign requested address > > The lo2 interface in rdomain 2 is configured as: > > lo2: flags=2008049 rdomain 2 mtu > 32768 > [...] > inet 2.3.0.6 netmask 0xffffffff > > And my /etc/hostname.pflow2 contains: > > rdomain 2 > flowsrc 2.3.0.6 flowdst 2.3.0.6:12345 > pflowproto 10 > > My question is whether this behavior is expected. ( i guess so ) In > this setup, the flow destination is in rdomain 0, and I'm trying to mark > flows based on their originating rdomain. > > More seriously, I was also wondering whether using the engine_id field > might be a > suitable way to store or represent the rdomain value, which is probably > a better way but would require a kernel update, something like : > > ```diff > RCS file: /cvs/src/sys/net/if_pflow.c,v > diff -u -p -r1.111 if_pflow.c > --- ./sys/net/if_pflow.c 7 Jul 2025 02:28:50 -0000 1.111 > +++ ./sys/net/if_pflow.c 10 Mar 2026 13:22:22 -0000 > @@ -111,7 +111,7 @@ int export_pflow_if(struct pf_state*, st > struct pflow_softc *); > int copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc); > int copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, > - struct pflow_softc *sc); > + struct pflow_softc *sc, uint16_t rdomain); > int copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow, > struct pflow_softc *sc); > > @@ -930,7 +930,8 @@ copy_flow_to_m(struct pflow_flow *flow, > } > > int > -copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, struct > pflow_softc *sc) > +copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, > + struct pflow_softc *sc, uint16_t rdomain) > { > int ret = 0; > > @@ -944,6 +945,7 @@ copy_flow_ipfix_4_to_m(struct pflow_ipfi > sc->sc_count4 = 0; > timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT); > } > + sc->engine_id = rdomain; > m_copyback(sc->sc_mbuf, PFLOW_SET_HDRLEN + > (sc->sc_count4 * sizeof(struct pflow_ipfix_flow4)), > sizeof(struct pflow_ipfix_flow4), flow, M_NOWAIT); > @@ -1030,10 +1032,10 @@ pflow_pack_flow_ipfix(struct pf_state *s > 0, 1); > > if (st->bytes[0] != 0) /* first flow from state */ > - ret = copy_flow_ipfix_4_to_m(&flow4_1, sc); > + ret = copy_flow_ipfix_4_to_m(&flow4_1, sc, > sk->rdomain); > > if (st->bytes[1] != 0) /* second flow from state */ > - ret = copy_flow_ipfix_4_to_m(&flow4_2, sc); > + ret = copy_flow_ipfix_4_to_m(&flow4_2, sc, > sk->rdomain); > } else if (sk->af == AF_INET6) { > bzero(&flow6_1, sizeof(flow6_1)); > ``` > > > It's incomplete and not completely suitable. ( Tabs / spaces. Even > my terminal does not copy tabs now, ignoring ipv6 ... ), but > certainly illustrate the feature better ! > > I'd appreciate any clarification on whether the errors above are > expected and whether the idea of using engine_id for rdomain tagging > makes sense, and could be included in future release > > > Happy Spring and thank you for reading that far. > NB: Meanwhile i'm downgrading to netflow5 and will test this : Index: ./sys/net/if_pflow.c =================================================================== RCS file: /cvs/src/sys/net/if_pflow.c,v diff -u -p -r1.111 if_pflow.c --- ./sys/net/if_pflow.c 7 Jul 2025 02:28:50 -0000 1.111 +++ ./sys/net/if_pflow.c 10 Mar 2026 15:10:07 -0000 @@ -86,7 +86,7 @@ void pflow_setmtu(struct pflow_softc *, int pflowvalidsockaddr(const struct sockaddr *, int); int pflowioctl(struct ifnet *, u_long, caddr_t); -struct mbuf *pflow_get_mbuf(struct pflow_softc *, u_int16_t); +struct mbuf *pflow_get_mbuf(struct pflow_softc *, u_int16_t, u_int16_t); void pflow_flush(struct pflow_softc *); int pflow_sendout_v5(struct pflow_softc *); int pflow_sendout_ipfix(struct pflow_softc *, sa_family_t); @@ -109,9 +109,9 @@ int pflow_pack_flow_ipfix(struct pf_stat struct pflow_softc *); int export_pflow_if(struct pf_state*, struct pf_state_key *, struct pflow_softc *); -int copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc); +int copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc, u_int16_t); int copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, - struct pflow_softc *sc); + struct pflow_softc *sc, u_int16_t rdomain); int copy_flow_ipfix_6_to_m(struct pflow_ipfix_flow6 *flow, struct pflow_softc *sc); @@ -657,7 +657,7 @@ pflow_setmtu(struct pflow_softc *sc, int } struct mbuf * -pflow_get_mbuf(struct pflow_softc *sc, u_int16_t set_id) +pflow_get_mbuf(struct pflow_softc *sc, u_int16_t set_id, u_int16_t rdomain) { struct pflow_set_header set_hdr; struct pflow_header h; @@ -693,7 +693,7 @@ pflow_get_mbuf(struct pflow_softc *sc, u h.version = htons(PFLOW_PROTO_5); h.flow_sequence = htonl(sc->sc_gcounter); h.engine_type = PFLOW_ENGINE_TYPE; - h.engine_id = PFLOW_ENGINE_ID; + h.engine_id = htons(rdomain); m_copyback(m, 0, PFLOW_HDRLEN, &h, M_NOWAIT); sc->sc_count = 0; @@ -905,14 +905,15 @@ export_pflow_if(struct pf_state *st, str } int -copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc) +copy_flow_to_m(struct pflow_flow *flow, struct pflow_softc *sc, + u_int16_t rdomain) { int ret = 0; MUTEX_ASSERT_LOCKED(&sc->sc_mtx); if (sc->sc_mbuf == NULL) { - if ((sc->sc_mbuf = pflow_get_mbuf(sc, 0)) == NULL) + if ((sc->sc_mbuf = pflow_get_mbuf(sc, 0, rdomain)) == NULL) return (ENOBUFS); } m_copyback(sc->sc_mbuf, PFLOW_HDRLEN + @@ -930,7 +931,8 @@ copy_flow_to_m(struct pflow_flow *flow, } int -copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, struct pflow_softc *sc) +copy_flow_ipfix_4_to_m(struct pflow_ipfix_flow4 *flow, + struct pflow_softc *sc, u_int16_t rdomain) { int ret = 0; @@ -938,12 +940,13 @@ copy_flow_ipfix_4_to_m(struct pflow_ipfi if (sc->sc_mbuf == NULL) { if ((sc->sc_mbuf = - pflow_get_mbuf(sc, PFLOW_IPFIX_TMPL_IPV4_ID)) == NULL) { + pflow_get_mbuf(sc, PFLOW_IPFIX_TMPL_IPV4_ID, rdomain)) == NULL) { return (ENOBUFS); } sc->sc_count4 = 0; timeout_add_sec(&sc->sc_tmo, PFLOW_TIMEOUT); } + // sc->engine_id = rdomain; // cant do that and v10 is crewed m_copyback(sc->sc_mbuf, PFLOW_SET_HDRLEN + (sc->sc_count4 * sizeof(struct pflow_ipfix_flow4)), sizeof(struct pflow_ipfix_flow4), flow, M_NOWAIT); @@ -966,7 +969,7 @@ copy_flow_ipfix_6_to_m(struct pflow_ipfi if (sc->sc_mbuf6 == NULL) { if ((sc->sc_mbuf6 = - pflow_get_mbuf(sc, PFLOW_IPFIX_TMPL_IPV6_ID)) == NULL) { + pflow_get_mbuf(sc, PFLOW_IPFIX_TMPL_IPV6_ID, 0)) == NULL) { return (ENOBUFS); } sc->sc_count6 = 0; @@ -1003,10 +1006,10 @@ pflow_pack_flow(struct pf_state *st, str copy_flow_data(&flow1, &flow2, st, sk, 0, 1); if (st->bytes[0] != 0) /* first flow from state */ - ret = copy_flow_to_m(&flow1, sc); + ret = copy_flow_to_m(&flow1, sc, sk->rdomain); if (st->bytes[1] != 0) /* second flow from state */ - ret = copy_flow_to_m(&flow2, sc); + ret = copy_flow_to_m(&flow2, sc, sk->rdomain); return (ret); } @@ -1030,10 +1033,10 @@ pflow_pack_flow_ipfix(struct pf_state *s 0, 1); if (st->bytes[0] != 0) /* first flow from state */ - ret = copy_flow_ipfix_4_to_m(&flow4_1, sc); + ret = copy_flow_ipfix_4_to_m(&flow4_1, sc, sk->rdomain); if (st->bytes[1] != 0) /* second flow from state */ - ret = copy_flow_ipfix_4_to_m(&flow4_2, sc); + ret = copy_flow_ipfix_4_to_m(&flow4_2, sc, sk->rdomain); } else if (sk->af == AF_INET6) { bzero(&flow6_1, sizeof(flow6_1)); bzero(&flow6_2, sizeof(flow6_2)); @@ -1225,7 +1228,7 @@ pflow_sendout_ipfix_tmpl(struct pflow_so if (!(ifp->if_flags & IFF_RUNNING)) { return (0); } - m = pflow_get_mbuf(sc, 0); + m = pflow_get_mbuf(sc, 0, 0); if (m == NULL) return (0); if (m_copyback(m, 0, sizeof(struct pflow_ipfix_tmpl),