On 08/26/2014 04:21 PM, Bala Manoharan wrote:
Hi,

Few points from my side,

1. We are creating pktio and then assigning the created queue to the pktio. IMO we should abstract the PKTIO, since it is up to the implementation to either support IPC through dummy interface or shared memory. Lets say if an implementation does IPC through shared memory there is no need for any PKTIO initialization.


pktio is needed for ipc thread as well. pkio describes where packet data is stored, while queue has only references for buffers in the pool. In my patch I just connect packet i/o entry with pool:
odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool,
               odp_pktio_params_t *params)

     case ODP_PKTIO_TYPE_IPC:
        pktio_entry->s.pool = pool;
        break;

The main goal is to make queue visible by different problem. And avoid coping packet body. So reference to original pool is needed.

2. We need to think about the design of how many receive queues are there per process, do we follow the design of one receive queue per process which means all the processes which wants to send message to process-A always enqueues into a queue named queue-process-A

As Mike replied we staid on one queue per process. That is better fit to hardware implementation. How ever in software we are more flexible (odp_ring has multiply consumers/producers).

3. Regarding synchronization, IMO if we agree that there will be only one receive queue per process, we can create IPC queues based on standard names, and when a process which needs IPC mechanism registers we can create the receive queue for that specific process and the process can issue find_IPC_queue() function using the standardised process name and get the queue handle for process to which it wants to send the message.

yep, I will implement that. For now it's hidden to platform implementation. But it's more right to use queue_lookup().


Maxim.

Regards,
Bala


On 26 August 2014 17:37, Ola Liljedahl <[email protected] <mailto:[email protected]>> wrote:

    Sharing queues between threads that share memory is not a big
    problem. But sharing queues between different programs/processes
    which do not want to share memory (e.g. between a control plane
    program and one or several dataplane applications) is a problem.
    It is not just the lookup of the queue identifier. Depending on
    the ODP implementation, some memory might have to be shared
    between these different processes even if the user code is (and
    wants to be) unaware of this. An implementation might get away
    from sharing memory in this case if either the HW can do the copy
    or if the ODP implementation calls the Linux kernel to perform the
    copy of buffers (messages).


    On 26 August 2014 14:03, Maxim Uvarov <[email protected]
    <mailto:[email protected]>> wrote:

        On 08/26/2014 03:13 PM, Ola Liljedahl wrote:

            Possibly we are missing a public API for looking up a
            queue (or perhaps specifically an IPC queue) by name.

            If you have two threads (in same or different processes)
            that first try to look up an (IPC or global) queue by name
            and if this fails then creates said IPC queue, you have
            introduced a race condition. Possibly the second IPC queue
            create will fail because the named queue exists (EEXIST)
            and the caller can then understand it does not have to
            create the queue.

            So I think we have some synchronization issues to
            understand and solve when it comes to IPC. Because the
            primary use case for IPC will be for communication between
            different programs (processes) so they have no means for
            synchronization (I would rather not have to use other
            Linux mechanisms for setting up an IPC channel).

        Ola, I agree with that. We have function to look up for pool,
        but don't have that function to loop up for queue. But it
        might be common case where different threads want to reference
        to single queue.

        odp_queue_t odp_queue_lookup(const char *name,
        odp_queue_type_t type)

        which will do:
        - walk over queue_tbl and compare name with argument, if name
        match return it;
        - if type ipc, search for shared memory object, if it's exist
        connect to it.

        Maxim.



            On 26 August 2014 11:48, Maxim Uvarov
            <[email protected] <mailto:[email protected]>
            <mailto:[email protected]
            <mailto:[email protected]>>> wrote:

                On 08/26/2014 12:56 PM, Taras Kondratiuk wrote:

                    On 08/25/2014 05:37 PM, Maxim Uvarov wrote:

                        I pushed here some raw code:
            
https://git.linaro.org/people/maxim.uvarov/odp.git/shortlog/refs/heads/odp_ipc2



                        Example here app here:
            
https://git.linaro.org/people/maxim.uvarov/odp.git/blob/refs/heads/odp_ipc2:/example/fork/odp_fork.c



                        pktio_queue_thread() takes packets from inq
            queue and put
                        them to ipc
                        queue.

                        ring_thread() takes packets from ipc queue and
            free this
                        buffer.


                    I have a few things I didn't understand:
                    1. It is not clear how IPC pktio and its pool is used.
                    Especially on
                    'sender' side.


                We create pool somewhere. Then do loop up for it:
                pkt_pool = odp_buffer_pool_lookup("packet_pool");

                Then we want that IPC queue can work with that pool.
            So we open
                pktio:

                    pktio_ipc_params.type = ODP_PKTIO_TYPE_IPC;
                    pktio_ipc = odp_pktio_open(NULL, pkt_pool,
            &pktio_ipc_params);

                And then create queue:

                ipcq_def = odp_queue_create("shared-queue",
            ODP_QUEUE_TYPE_IPC,
                &qparam);

                when we place packet to this queue with:
                odp_queue_enq(ipcq_def, buf);

                Than everything depend on implementation. So linux-generic
                (software), packet data
                still will be in pool. odp_buffer_t (uint32_t) value
            will be added
                to ring.

                Other process gets odp_buffer_t, and find pointer to
            that buffer
                (odp_buffer_hdr_t*).

                On hw implementation you just place odp_buffer_t to
            the queue. And
                if ipc queue has the same
                pool than packet can be delivered to software. If
            there are
                different pools, then packet should be
                copied to ipc pool, and after that delivered to hardware.

                The main goal here is we can say that ipc pool can be
            the same as
                ingress pool or it can be different.
                Depends on hw configuration.


                    2. On both sides IPC queue is created. My
            impression was that
                    it should
                    be looked up on one side via pktio or directly via
            queue name.


                Is there way to ask hardware which queues were already
            created?

                Actually I do look up, but it's hidden in
            implementation. Idea is
                that if queue type is IPC,
                then I do loop up if that queue already exist. If
            exist then I
                connect to that queue. If it does
                not exist - I create it.

                static void queue_init(queue_entry_t *queue, const
            char *name,
                               odp_queue_type_t type,
            odp_queue_param_t *param)

                    case ODP_QUEUE_TYPE_IPC:
                        queue->s.r = odp_ring_lookup(name);

                        if (!queue->s.r)
                        {
                            printf("creating new odp ring: %s\n", name);
                            queue->s.r = odp_ring_create(name, RING_SIZE,
                ODP_RING_SHM_PROC);
                            if (queue->s.r == NULL) {
                                ODP_ERR("ring create failed\n");
                            }
                        } else
                            printf("odp ring found!!!\n");

                Because of we can say that several processes can
            connect to one
                queue, there is no difference
                which exactly process will create this queue. So my
            idea was to
                stay with original odp_queue_create() app API.

                Thanks,
                Maxim.






                _______________________________________________
                lng-odp mailing list
            [email protected] <mailto:[email protected]>
            <mailto:[email protected]
            <mailto:[email protected]>>
            http://lists.linaro.org/mailman/listinfo/lng-odp





    _______________________________________________
    lng-odp mailing list
    [email protected] <mailto:[email protected]>
    http://lists.linaro.org/mailman/listinfo/lng-odp




_______________________________________________
lng-odp mailing list
[email protected]
http://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to