> >>> @@ -209,23 +218,79 @@ static int tipc_udp_send_msg(struct net *net,
struct sk_buff *skb,
> >>> if (skb_headroom(skb) < UDP_MIN_HEADROOM) {
> >>> err = pskb_expand_head(skb, UDP_MIN_HEADROOM, 0,
GFP_ATOMIC);
> >>> if (err)
> >>> - goto tx_error;
> >>> + goto err_out;
> >>> }
> >>>
> >>> skb_set_inner_protocol(skb, htons(ETH_P_TIPC));
> >>> ub = rcu_dereference_rtnl(b->media_ptr);
> >>> if (!ub) {
> >>> err = -ENODEV;
> >>> - goto tx_error;
> >>> + goto err_out;
> >>> + }
> >>> +
> >>> + /* Replicast, send an skb to each configured IP address */
> >>> + if (unlikely(addr->broadcast)) {
> >>> + bool first = true;
> >>> + struct udp_replicast *rcast;
> >>> +
> >>> + list_for_each_entry_rcu(rcast, &ub->rcast.list, list) {
> >>> + struct sk_buff *_skb;
> >>> +
> >>> + /* Avoid one extra skb copy */
> >>> + if (first) {
> >>> + dst = &rcast->addr;
> >>> + first = false;
> >>> + continue;
> >>> + }
> >>> +
> >>> + _skb = pskb_copy(skb, GFP_ATOMIC);
> >>> + if (!_skb) {
> >>> + err = -ENOMEM;
> >>> + goto err_out;
> >>> + }
> >>> +
> >>> + err = tipc_udp_xmit(net, _skb, ub, src,
&rcast->addr);
> >>> + if (err) {
> >>> + kfree_skb(_skb);
> >>> + goto err_out;
> >>> + }
> >>> + }
> >> Slightly confusing. Why don't you return here? Even when the list is
> >> non-empty you go on and send to the first given address, which may or
> >> may not be a multicast address.
> >> It is probably correct, but the logics is not intuitive. Maybe some
> >> refactoring and comments will help?
> > We avoid an extra skb clone.
> > The logic is as follows.
> >
> > We always have an skb when we come here.
> > * If this is a multicast bearer, we skip the replicast code and send it
> > as it is.
> > * If it's a peer-to-peer bearer we sent it to the first address in the
> > replicast list, i.e. our peer.
> I don't think the concept of peer-to-peer bearer even exists from now
> on. To me it is just a (very unusual) special case of a replicast bearer
> where N == 1, and it deserves no special consideration in the code if we
> do things right.
>
> > * If it's a replicast bearer, we send a skb copy to all but the first
> > peer, which gets the original skb. This way we avoid an extra
> > skb_copy() and skb_free().
> A cloning extra is nothing if you are anyway replicasting to N >> 1
> nodes. Code clarity should be more important.
>
> What about:
>
> if (!addr->broadcast || skb_queue_empty(list))
> return tipc_udp_xmit(net, skb, ub, src, dst);
>
> /* Replicast */
> list_for_each_entry(...) {
> clone;
> xmit;
> }
> skb_free(skb);
>
>
> I think this would be easier to understand. Here I assume that the peer
> list is empty if we have multicast bearer, and that all peer addresses
> only exist in the form of media addresses in the individual links. If
> the peer list for some reason I don't understand cannot be empty, we
> have to find some other way to distinguish between multicast and
> replicast, such as a separate 'replicast' value in tipc_media_address.
>
> >
> > This is an effect of moving the peer-to-peer address
> If the "peer-to-peer" address *is* a multicast address it should go to
> the broadcast field, otherwise it should be added at the first address
> in the list.
>
> BR
> ///jon
>
IMHO, If you cannot quantify the performance gain of adding special
consideration for the N=1 case, it's not needed.
//E
------------------------------------------------------------------------------
_______________________________________________
tipc-discussion mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tipc-discussion