On Mon, 2016-08-29 at 07:35 -0400, Jamal Hadi Salim wrote: > flags = READ_ONCE(d->flags); > rcu_read_lock(); > if (flags & SKBMOD_F_DMAC) > ether_addr_copy(eth_hdr(skb)->h_dest, d->eth_dst); > if (flags & SKBMOD_F_SMAC) > ether_addr_copy(eth_hdr(skb)->h_source, d->eth_src); > if (flags & SKBMOD_F_ETYPE) > eth_hdr(skb)->h_proto = d->eth_type; > if (flags & SKBMOD_F_SWAPMAC) { > u8 tmpaddr[ETH_ALEN]; > /*XXX: I am sure we can come up with something more > efficient */ > ether_addr_copy(tmpaddr, eth_hdr(skb)->h_dest); > ether_addr_copy(eth_hdr(skb)->h_dest, > eth_hdr(skb)->h_source); > ether_addr_copy(eth_hdr(skb)->h_source, tmpaddr); > } > rcu_read_unlock();
You would need to store everything in an object, managed by rcu. struct my_rcu_safe_struct { u32 flags; u8 eth_dst[ETH_ALEN]; u8 eth_src[ETH_ALEN]; __be16 eth_type; }; And then allocate a new one when you need to update the infos (from tcf_skbmod_init(()) RCU : Read Copy Update. Then in the reader you would use rcu_read_lock(); myptr = rcu_dereference(d->ptr); if (myptr) { if (myptr->flags & SKBMOD_F_DMAC) ether_addr_copy(eth_hdr(skb)->h_dest, myptr->eth_dst); if (myptr->flags & SKBMOD_F_SMAC) ether_addr_copy(eth_hdr(skb)->h_source, myptr->eth_src); if (myptr->flags & SKBMOD_F_ETYPE) eth_hdr(skb)->h_proto = myptr->eth_type; } rcu_read_unlock();