Thanks Damjan,

This clarifies things regarding the cloning mechanism. However using
n_clones=2 and putting the 2nd clone in the frame still results
in the buffer being sent only to the host interface, the flow I'm using is
this: (minimal example)

// getting host interface node index from sw if index
> vnet_hw_interface_t * host_intf = vnet_get_sup_hw_interface (vnm,
> sw_if_index);
> u32 host_interface_node_index = host_intf->tx_node_index;
>
> // original frame
> vlib_frame_t *frame = vlib_get_frame_to_node(vm, node_index);
> u32 *to_next = vlib_frame_vector_args (frame);
>
> // frame for the cloned packet
> vlib_frame_t *host_if_frame = vlib_get_frame_to_node(vm,
> host_interface_node_index);
> u32 *intf_host_to_next = vlib_frame_vector_args (host_if_frame);
> host_if_frame->n_vectors = 1;
>
> // cloning the buffer
> u32 cbi0[2];
> u16 n_cloned = vlib_buffer_clone (vm, bi0, &cbi0, 2,
> VLIB_BUFFER_CLONE_HEAD_SIZE);
>
> // enqueuing both packets to two different nodes
> to_next[0] = bi0;
> intf_host_to_next[0] = cbi0[1];
> vlib_put_frame_to_node (vm, node_index, frame);
> vlib_put_frame_to_node (vm, host_interface_node_index, host_if_frame);
>

This results in the packet being sent only to host interface. I've checked
vpp source code for similar use cases that use buffer cloning
but didn't find a place when a node mirrors a packet and enqueues it to two
different nodes.

On Thu, Apr 8, 2021 at 1:04 PM Damjan Marion <[email protected]> wrote:

>
> You need to say n_clones = 2 to get 2.
> ref_cnt is updated only on tail buffer if tail buffer(s) exists.
> Head buffers always have ref_cnt = 1.
>
> Reason for that is that you actually never want to clone head buffer
> simply as if packet goes to 2
> different interfaces it needs to have different L2 headers.
>
> So it works as follows:
>
> if n_clones = 1, simply return same buffer index
>
> if n_clones > 1 and packet size is < VLIB_BUFFER_CLONE_HEAD_SIZE:
>  - allocate (n_clones-1) new buffers
>  - memcpy whole payload from original buffer to each allocated buffer
>
> if n_clones > 1 and packet size is >= VLIB_BUFFER_CLONE_HEAD_SIZE
>  - allocate (n_clones) new buffers
>  - for each allocated buffer:
>    - memcpy first VLIB_BUFFER_CLONE_HEAD_SIZE bytes of payload from
> original buffer
>    - set b->next_buffer_index to point to the original buffer
>  - advance b->current_data for VLIB_BUFFER_CLONE_HEAD_SIZE
>  - set b->ref_cnt of the original buffer (and all his tails) to be n_clones
>
>
> Hope this explains…
>
> —
> Damjan
>
>
>
>
>
> > On 08.04.2021., at 11:37, David Gohberg <[email protected]> wrote:
> >
> > Hi,
> >
> > In my node processing function, I want some buffers to be cloned and
> sent to a specific host interface while also be sent to the "normal"
> interface resolved in the node.
> > At the end, the node should be able to send the buffers to two different
> interfaces simultaneously.
> > packet -> node -> interface 1
> >                     |
> >                    V
> >                 cloned packet
> >                 to host interface
> >
> > In my single loop where I process the buffers I added a call to this
> function:
> >
> > static inline void replicate_and_send_buffer(vnet_main_t *vnm,
> vlib_main_t * vm,
> >                                 vlib_node_runtime_t * node,
> >                                 u32 bi0,
> >                                 u16 sw_if_index)
> > {
> >         u32 cbi0;
> >         u16 n_cloned = vlib_buffer_clone (vm, bi0, &cbi0, 1,
> VLIB_BUFFER_CLONE_HEAD_SIZE);
> >         vnet_hw_interface_t * host_intf = vnet_get_sup_hw_interface
> (vnm, sw_if_index);
> >         u32 node_index = host_intf->tx_node_index;
> >         vlib_frame_t *host_if_frame = vlib_get_frame_to_node(vm,
> node_index);
> >         host_if_frame->n_vectors = 1;
> >         u32 *to_next = vlib_frame_vector_args (host_if_frame);
> >         to_next[0] = cbi0;
> >         vlib_put_frame_to_node (vm, node_index, host_if_frame);
> > }
> >
> > What is happening here is that I clone the original buffer and put it in
> a frame corresponding to the host interface node (in addition to the frame
> of the main loop pointing to a different node)
> > Running this code leads me to double-free crash.
> >
> > I noticed that vlib_buffer_clone, when asked to create 1 clone,
> presented me with a new buffer index that has the same address as the
> original buffer, but the ref_count stays 1. Looking at the
> vlib_buffer_clone confirms that it only copies the packet for n_clones > 1,
> but still not updating the ref_count. So it looks like I'm missing
> something wrt how the cloning works.
> >
> > I changed the code to create 2 clones and tried to use the 2nd clone in
> the host interface frame. This resulted in the packet being sent only to
> the host interface, but not to both of the interfaces.
> >
> > I'm probably doing something wrong, how can I achieve the desired
> behavior?
> >
> > Thanks,
> > David
> >
> > 
> >
>
>
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#19144): https://lists.fd.io/g/vpp-dev/message/19144
Mute This Topic: https://lists.fd.io/mt/81938105/21656
Group Owner: [email protected]
Unsubscribe: https://lists.fd.io/g/vpp-dev/unsub [[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to