From patchwork Mon Jul 3 08:00:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 106887 Delivered-To: patch@linaro.org Received: by 10.140.101.44 with SMTP id t41csp5485973qge; Mon, 3 Jul 2017 01:02:29 -0700 (PDT) X-Received: by 10.200.33.209 with SMTP id 17mr1601833qtz.189.1499068949344; Mon, 03 Jul 2017 01:02:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1499068949; cv=none; d=google.com; s=arc-20160816; b=lPdZdd10tSwelLacD8G+8m9pYkrZWx60TvXo2I9xlLHf8za7LBq9iVY8umBPp5RsmA mLOIvTzPS9hXrSSh5hA67naLMp/xFkIG+E1pVRYkrZnx8qBLjgx9MpVdS8a+5AHbziPT XpsvmWbJHdtmtKquT6wRDccIIVR+8CwH4k8KR4yFDWvK/UoAht5Ks47WQhqoCgJo3a+v oFUEm/AZFiZk0uQvdDeW9rvybiFkoDuEBtLy9K7hGxUNXs240vOhg0InzW6B66yyufim bZ21zlutcsS94zlhLJ2kzouIcxlDHJOUfKjFZYVpEIIi2IKlaNFklB+nRz/KzKQ/pexp m66Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:github-pr-num :references:in-reply-to:message-id:date:to:from:delivered-to :arc-authentication-results; bh=OZ/Zi6XlWBxnDmlQcgNcGZ8mR6j5Pm5vOCQteMZIGbY=; b=iMb5lzSUZBsMJddr6xb781EfewD46jxAOqe+0DZQat4kmcFlvxi12lbxRzT5cHhRbg 1YeN4GbK2cXvWA+Op++Y1ndGiG+3SmgCrBMEJvLXZR1ZyrMPZZEMtKSsTnK0y5DrDCfJ V62hSW9zOOpTJkM1ZW7Fdi0MMbn5i6Y4hHwpOhAB3hZrlJ75TiXIaqi8WIj509B3LdzX aWiaKw9z+Bz5qL9I1xradOuvvztEFPfwkoiayqtet2m1RjqtYcO0azajh3/7LaGX2GTA ICTUg0uEb8Q90O2O+3Qg+QNFNhNZoJxstNE7GwKMLYYXb0YOLnW5o6G0ie+9lLfaGm5G hzeQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id n73si14147562qkl.323.2017.07.03.01.02.29; Mon, 03 Jul 2017 01:02:29 -0700 (PDT) Received-SPF: pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Received: by lists.linaro.org (Postfix, from userid 109) id ED980608B8; Mon, 3 Jul 2017 08:02:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, URIBL_BLOCKED, URIBL_SBL, URIBL_SBL_A autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id D6500609F8; Mon, 3 Jul 2017 08:00:52 +0000 (UTC) X-Original-To: lng-odp@lists.linaro.org Delivered-To: lng-odp@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 4DECA6071E; Mon, 3 Jul 2017 08:00:33 +0000 (UTC) Received: from forward4p.cmail.yandex.net (forward4p.cmail.yandex.net [77.88.31.19]) by lists.linaro.org (Postfix) with ESMTPS id AABBD609F8 for ; Mon, 3 Jul 2017 08:00:19 +0000 (UTC) Received: from smtp2m.mail.yandex.net (smtp2m.mail.yandex.net [IPv6:2a02:6b8:0:2519::122]) by forward4p.cmail.yandex.net (Yandex) with ESMTP id B299D20EAE for ; Mon, 3 Jul 2017 11:00:17 +0300 (MSK) Received: from smtp2m.mail.yandex.net (localhost.localdomain [127.0.0.1]) by smtp2m.mail.yandex.net (Yandex) with ESMTP id D99642300D70 for ; Mon, 3 Jul 2017 11:00:16 +0300 (MSK) Received: by smtp2m.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id CsmfCNkM5d-0FNe86kF; Mon, 03 Jul 2017 11:00:15 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (Client certificate not present) X-Yandex-Suid-Status: 1 0 From: Github ODP bot To: lng-odp@lists.linaro.org Date: Mon, 3 Jul 2017 11:00:08 +0300 Message-Id: <1499068809-20327-2-git-send-email-odpbot@yandex.ru> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1499068809-20327-1-git-send-email-odpbot@yandex.ru> References: <1499068809-20327-1-git-send-email-odpbot@yandex.ru> Github-pr-num: 65 Subject: [lng-odp] [PATCH CLOUD-DEV v1] [RFC 1/2] odp: add modular framework X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "The OpenDataPlane \(ODP\) List" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: lng-odp-bounces@lists.linaro.org Sender: "lng-odp" From: Yi He Add modular programming framework to support runtime selectable implementations for variant software subsystems. Signed-off-by: Yi He --- /** Email created from pull request 65 (heyi-linaro:modular-framework) ** https://github.com/Linaro/odp/pull/65 ** Patch: https://github.com/Linaro/odp/pull/65.patch ** Base sha: 1ba26aa5650c05718c177842178de6d0f70b7fc1 ** Merge commit sha: f0f96a26d22e16b9299777cd413dfd6ae89a024e **/ modular-framework/list.h | 620 +++++++++++++++++++++ modular-framework/module.c | 158 ++++++ modular-framework/module.h | 205 +++++++ modular-framework/rwlock.h | 88 +++ platform/linux-generic/Makefile.am | 11 + .../include/odp/api/plat/atomic_types.h | 2 + .../include/odp/api/plat/rwlock_types.h | 2 + 7 files changed, 1086 insertions(+) create mode 100644 modular-framework/list.h create mode 100644 modular-framework/module.c create mode 100644 modular-framework/module.h create mode 100644 modular-framework/rwlock.h diff --git a/modular-framework/list.h b/modular-framework/list.h new file mode 100644 index 00000000..366d9f38 --- /dev/null +++ b/modular-framework/list.h @@ -0,0 +1,620 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +#include + +#if defined(__STDC__) +#define typeof __typeof__ +#endif + +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ + +#define LIST_POISON1 ((void *) 0x100) +#define LIST_POISON2 ((void *) 0x200) + +/* + * Prevent the compiler from merging or refetching reads or writes. The + * compiler is also forbidden from reordering successive instances of + * READ_ONCE, WRITE_ONCE and ACCESS_ONCE (see below), but only when the + * compiler is aware of some particular ordering. One way to make the + * compiler aware of ordering is to put the two invocations of READ_ONCE, + * WRITE_ONCE or ACCESS_ONCE() in different C statements. + */ + +#define READ_ONCE(x) \ +({ \ + volatile typeof(x) *__p = &(x); \ + *__p; \ +}) + +#define WRITE_ONCE(x, val) \ +({ \ + volatile typeof(x) *__p = &(x); \ + *__p = (typeof(x)) (val); \ +}) + +#define container_of(ptr, type, member) \ +({ \ + typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type, member) ); \ +}) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + WRITE_ONCE(list->next, list); + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + WRITE_ONCE(prev->next, new); +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + WRITE_ONCE(prev->next, next); +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void __list_del_entry(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +static inline void list_del(struct list_head *entry) +{ + __list_del_entry(entry); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace(struct list_head *old, + struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} + +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del_entry(entry); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del_entry(list); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del_entry(list); + list_add_tail(list, head); +} + +/** + * list_is_last - tests whether @list is the last entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_last(const struct list_head *list, + const struct list_head *head) +{ + return list->next == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return READ_ONCE(head->next) == head; +} + +/** + * list_empty_careful - tests whether a list is empty and not being modified + * @head: the list to test + * + * Description: + * tests whether a list is empty _and_ checks that no other CPU might be + * in the process of modifying either member (next or prev) + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +/** + * list_rotate_left - rotate the list to the left + * @head: the head of the list + */ +static inline void list_rotate_left(struct list_head *head) +{ + struct list_head *first; + + if (!list_empty(head)) { + first = head->next; + list_move_tail(first, head); + } +} + +/** + * list_is_singular - tests whether a list has just one entry. + * @head: the list to test. + */ +static inline int list_is_singular(const struct list_head *head) +{ + return !list_empty(head) && (head->next == head->prev); +} + +static inline void __list_cut_position(struct list_head *list, + struct list_head *head, struct list_head *entry) +{ + struct list_head *new_first = entry->next; + list->next = head->next; + list->next->prev = list; + list->prev = entry; + entry->next = list; + head->next = new_first; + new_first->prev = head; +} + +/** + * list_cut_position - cut a list into two + * @list: a new list to add all removed entries + * @head: a list with entries + * @entry: an entry within head, could be the head itself + * and if so we won't cut the list + * + * This helper moves the initial part of @head, up to and + * including @entry, from @head to @list. You should + * pass on @entry an element you know is on @head. @list + * should be an empty list or a list you do not care about + * losing its data. + * + */ +static inline void list_cut_position(struct list_head *list, + struct list_head *head, struct list_head *entry) +{ + if (list_empty(head)) + return; + if (list_is_singular(head) && + (head->next != entry && head != entry)) + return; + if (entry == head) + INIT_LIST_HEAD(list); + else + __list_cut_position(list, head, entry); +} + +static inline void __list_splice(const struct list_head *list, + struct list_head *prev, + struct list_head *next) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + + first->prev = prev; + prev->next = first; + + last->next = next; + next->prev = last; +} + +/** + * list_splice - join two lists, this is designed for stacks + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(const struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head, head->next); +} + +/** + * list_splice_tail - join two lists, each list being a queue + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice_tail(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head->prev, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head, head->next); + INIT_LIST_HEAD(list); + } +} + +/** + * list_splice_tail_init - join two lists and reinitialise the emptied list + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * Each of the lists is a queue. + * The list at @list is reinitialised + */ +static inline void list_splice_tail_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head->prev, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_last_entry - get the last element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_last_entry(ptr, type, member) \ + list_entry((ptr)->prev, type, member) + +/** + * list_first_entry_or_null - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note that if the list is empty, it returns NULL. + */ +#define list_first_entry_or_null(ptr, type, member) ({ \ + struct list_head *head__ = (ptr); \ + struct list_head *pos__ = READ_ONCE(head__->next); \ + pos__ != head__ ? list_entry(pos__, type, member) : NULL; \ +}) + +/** + * list_next_entry - get the next element in list + * @pos: the type * to cursor + * @member: the name of the list_head within the struct. + */ +#define list_next_entry(pos, member) \ + list_entry((pos)->member.next, typeof(*(pos)), member) + +/** + * list_prev_entry - get the prev element in list + * @pos: the type * to cursor + * @member: the name of the list_head within the struct. + */ +#define list_prev_entry(pos, member) \ + list_entry((pos)->member.prev, typeof(*(pos)), member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + pos != (head); \ + pos = n, n = pos->prev) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_first_entry(head, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_next_entry(pos, member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_last_entry(head, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_prev_entry(pos, member)) + +/** + * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_head within the struct. + * + * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - continue iteration over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Continue to iterate over list of given type, continuing after + * the current position. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_next_entry(pos, member); \ + &pos->member != (head); \ + pos = list_next_entry(pos, member)) + +/** + * list_for_each_entry_continue_reverse - iterate backwards from the given point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Start to iterate over list of given type backwards, continuing after + * the current position. + */ +#define list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = list_prev_entry(pos, member); \ + &pos->member != (head); \ + pos = list_prev_entry(pos, member)) + +/** + * list_for_each_entry_from - iterate over list of given type from the current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate over list of given type, continuing from current position. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; &pos->member != (head); \ + pos = list_next_entry(pos, member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_first_entry(head, typeof(*pos), member), \ + n = list_next_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = list_next_entry(n, member)) + +/** + * list_for_each_entry_safe_continue - continue list iteration safe against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate over list of given type, continuing after current point, + * safe against removal of list entry. + */ +#define list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = list_next_entry(pos, member), \ + n = list_next_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = list_next_entry(n, member)) + +/** + * list_for_each_entry_safe_from - iterate over list from current point safe against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate over list of given type from current point, safe against + * removal of list entry. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_next_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = list_next_entry(n, member)) + +/** + * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate backwards over list of given type, safe against removal + * of list entry. + */ +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_last_entry(head, typeof(*pos), member), \ + n = list_prev_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = list_prev_entry(n, member)) + +/** + * list_safe_reset_next - reset a stale list_for_each_entry_safe loop + * @pos: the loop cursor used in the list_for_each_entry_safe loop + * @n: temporary storage used in list_for_each_entry_safe + * @member: the name of the list_head within the struct. + * + * list_safe_reset_next is not safe to use in general if the list may be + * modified concurrently (eg. the lock is dropped in the loop body). An + * exception to this is if the cursor element (pos) is pinned in the list, + * and list_safe_reset_next is called after re-taking the lock and before + * completing the current iteration of the loop body. + */ +#define list_safe_reset_next(pos, n, member) \ + n = list_next_entry(pos, member) + +#endif diff --git a/modular-framework/module.c b/modular-framework/module.c new file mode 100644 index 00000000..6f80d938 --- /dev/null +++ b/modular-framework/module.c @@ -0,0 +1,158 @@ +/* Copyright (c) 2017, ARM Limited. All rights reserved. + * + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "module.h" + +#define MODULE_FRAMEWORK_VERSION 0x00010000UL +SUBSYSTEM(module, "module framework", MODULE_FRAMEWORK_VERSION); + +/* Keep it simple, allow one registration session at a time. */ +static struct { + rwlock_t lock; + subsystem_t *subsystem; + module_base_t *module; +} registration = { + .lock = RW_LOCK_UNLOCKED(lock), + .subsystem = NULL, + .module = NULL, +}; + +#define REGISTRATION_SANITY_CHECK(subsystem, module) \ +do { \ + if (subsystem == NULL || module == NULL) \ + return -ENOENT; \ + \ + if (!list_empty(&module->list)) { \ + printf("module %s was already registered.\n", \ + module->name); \ + return -EAGAIN; \ + } \ +} while(0) + +/* Module is linked statically or dynamically, and are loaded by + * program loader (execve) or dynamic linker/loader (ld.so) + * + * subsystem_register_module() should complete the whole registration + * session and link the module into subsystem's module array. + */ +static int linker_register_module( + subsystem_t *subsystem, module_base_t *module) +{ + REGISTRATION_SANITY_CHECK(subsystem, module); + + /* Allow one registration session at a time */ + rwlock_write_lock(®istration.lock); + + /* Block the subsystem API calls in load new + * implementation modules. */ + rwlock_write_lock(&subsystem->lock); + module->handler = NULL; /* no DSO handler */ + list_add(&module->list, &subsystem->modules); + rwlock_write_unlock(&subsystem->lock); + + rwlock_write_unlock(®istration.lock); + return 0; +} + +static int (*do_register_module)(subsystem_t *, module_base_t *) + = &linker_register_module; + +static int loader_register_module( + subsystem_t *subsystem, module_base_t *module) +{ + REGISTRATION_SANITY_CHECK(subsystem, module); + + /* Registration session lock must be held by + * module_loader_start(). */ + if (rwlock_write_trylock(®istration.lock) == 0) { + registration.subsystem = subsystem; + registration.module = module; + return 0; + } + + rwlock_write_unlock(®istration.lock); + return -EACCES; +} + +void module_loader_start(void) +{ + rwlock_write_lock(®istration.lock); + + if (registration.module != NULL || + registration.subsystem != NULL) { + printf("module loader start warn, A previous " + "registration did not complete yet.\n"); + } + + registration.module = NULL; + registration.subsystem = NULL; + do_register_module = &loader_register_module; +} + +void module_loader_end(void) +{ + if (registration.module != NULL || + registration.subsystem != NULL) { + printf("module loader end warn, A previous " + "registration did not complete yet.\n"); + } + + registration.module = NULL; + registration.subsystem = NULL; + do_register_module = &linker_register_module; + + rwlock_write_unlock(®istration.lock); +} + +int module_install_dso(void *dso) +{ + /* Bottom halves of the registration, context exclusion + * is guarenteed by module_loader_start() + */ + if (0 == rwlock_write_trylock(®istration.lock)) { + subsystem_t *subsystem = registration.subsystem; + module_base_t *module = registration.module; + + if (subsystem != NULL && module != NULL) { + rwlock_write_lock(&subsystem->lock); + module->handler = dso; + list_add(&module->list, &subsystem->modules); + rwlock_write_unlock(&subsystem->lock); + } + + registration.subsystem = NULL; + registration.module = NULL; + return 0; + } + + rwlock_write_unlock(®istration.lock); + return -EACCES; +} + +int module_abandon_dso(void) +{ + /* Bottom halves of the registration, context exclusion + * is guarenteed by module_loader_start() + */ + if (0 == rwlock_write_trylock(®istration.lock)) { + registration.subsystem = NULL; + registration.module = NULL; + return 0; + } + + rwlock_write_unlock(®istration.lock); + return -EACCES; +} + +int __subsystem_register_module( + subsystem_t *subsystem, module_base_t *module) +{ + return do_register_module(subsystem, module); +} diff --git a/modular-framework/module.h b/modular-framework/module.h new file mode 100644 index 00000000..e26ca3aa --- /dev/null +++ b/modular-framework/module.h @@ -0,0 +1,205 @@ +/* Copyright (c) 2017, ARM Limited. All rights reserved. + * + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * + * Modular programming framework supports runtime selectable + * implementations for variant software subsystems. + * + * Multiple implementations of the same subsystem can be built + * into individual static libraries or loadable DSOs, and use + * constructor functions to register themselves. + * + * A subsystem can choose one active implementation and provide + * APIs to switch between implementations. + * + * Alternatively, subsystem can load multiple implementations + * and determine the APIs route in runtime. + + * Also in need to pursue extreme performance the subsystem + * can choose one specific implementation module and build it + * to override subsystem API symbols directly, thus eliminate + * one level indirection of API calls through function pointers. + * + * This framework tries to minimizes dependencies to the linked + * list and rwlock facilities only. + */ + +#ifndef MODULE_H +#define MODULE_H + +#include "list.h" +#include "rwlock.h" + +typedef struct { + rwlock_t lock; + uint32_t version; + const char *name; + const char *description; + struct list_head modules; + struct list_head *active; +} subsystem_t; + +/* Subsystem instance name */ +#define subsystem(name) name ## _subsystem + +/* The trick is to use macro SUBSYSTEM() for both subsystem + * declaration and definition. ARGC() macro chooses either + * SUBSYSTEM_DEFINE() or SUBSYSTEM_DECLARE() depends on argument + * number, + */ +#define _ARGC(_0, _1, _2, _3, ...) _3 +#define ARGC(...) _ARGC(__VA_ARGS__, DEFINE, 2, DECLARE, 0) + +#define _OVERLOAD(M, S, ...) M ## _ ## S(__VA_ARGS__) +#define OVERLOAD(M, S, ...) _OVERLOAD(M, S, __VA_ARGS__) + +#define SUBSYSTEM_DEFINE(_name, _description, _version) \ + subsystem_t subsystem(_name) = { \ + .lock = RW_LOCK_UNLOCKED(lock), \ + .name = # _name, \ + .version = _version, \ + .description = _description, \ + } + +#define SUBSYSTEM_DECLARE(name) subsystem_t subsystem(name) +#define SUBSYSTEM(...) OVERLOAD(SUBSYSTEM, ARGC(__VA_ARGS__), __VA_ARGS__) + +/* Subsystem API prototype name */ +#define api_proto(subsystem, api) subsystem ##_## api ## _proto_t + +/* Subsystem API declaration */ +#define SUBSYSTEM_API(name, _return, api, ...) \ + extern _return name ##_## api(__VA_ARGS__); \ + typedef _return (*api_proto(name, api))(__VA_ARGS__) \ + +/* Subsystem API stubs are weak */ +#define SUBSYSTEM_API_STUB(name, api) \ + __attribute__((weak)) name ##_## api + +/* In case subsystem API implementations are built as static + * libraries or preload DSOs, one implementation can use this + * macro to override the APIs weak stubs. + */ +#define SUBSYSTEM_API_OVERRIDE(name, api, _alias) \ + __attribute__((alias(#_alias))) name ##_## api + +#define subsystem_constructor(name) \ + do { \ + rwlock_init(&subsystem(name).lock); \ + INIT_LIST_HEAD(&subsystem(name).modules); \ + subsystem(name).active = NULL; \ + } while(0) + +#define SUBSYSTEM_CONSTRUCTOR(name) \ + static void __attribute__((constructor(101))) \ + name ## _subsystem_constructor(void) + +#define subsystem_lock(access, name) \ + rwlock_ ##access## _lock(&subsystem(name).lock) + +#define subsystem_unlock(access, name) \ + rwlock_ ##access## _unlock(&subsystem(name).lock) + +#define subsystem_foreach_module(name, mod) \ + list_for_each_entry(mod, &subsystem(name).modules, list) + +#define MODULE_CLASS(subsystem) \ + struct subsystem ## _module { \ + struct list_head list; \ + const char *name; \ + void *handler; /* DSO */ \ + int (*init_local)(void); \ + int (*term_local)(void); \ + int (*init_global)(void); \ + int (*term_global)(void); \ + +/* Base class to all inherited subsystem module classes */ +typedef MODULE_CLASS(base) } module_base_t; + +/* Module constructors should be late than subsystem constructors, + * in statically linked scenarios (both subsystems and modules are + * linked statically). thus the priority 102 compared to the above + * subsystem constructor priority 101. + */ +#define MODULE_CONSTRUCTOR(name) \ + static void __attribute__((constructor(102))) \ + name ## _module_constructor(void) + +/* All subsystems' initialization and termination routines are + * the same, provide template to instantiation. + */ +#define SUBSYSTEM_INITERM_TEMPLATE(subs, method, print) \ +static inline int subs ## _subsystem ##_## method(void) \ +{ \ + module_base_t *mod = NULL; \ + \ + subsystem_lock(read, subs); \ + subsystem_foreach_module(subs, mod) { \ + int result = mod->method ? mod->method() : -1; \ + if (result < 0) { \ + subsystem_unlock(read, subs); \ + print("error %d to %s subsystem %s " \ + "module %s.\n", result, # method, \ + subsystem(subs).name, mod->name); \ + return result; \ + } \ + } \ + subsystem_unlock(read, subs); \ + return 0; \ +} + +/* Subsystem Modules Registration + * + * subsystem_register_module() are called by all modules in their + * constructors, whereas the modules could be: + * + * 1) Linked statically or dynamically, and are loaded by program + * loader (execve) or dynamic linker/loader (ld.so) + * + * subsystem_register_module() should complete the whole + * registration session and link the module into subsystem's + * module array. + * + * 2) Loaded by a module loader in runtime with libdl APIs + * + * The whole registration session needs to be split to aim the + * module loader to properly handle dlopen() returns, and save + * the DSO handler into module's data structure. + * + * The module loader should program in this way: + * module_loader_start(); + * ...... + * for each module + * handler = dlopen(module) + * -- the module constructor calls register_module() + * if (handler is valid) + * install_dso(handler); + * else + abandon_dso(); + * ...... + * module_loader_end(); + */ + +extern void module_loader_start(void); +extern void module_loader_end(void); + +extern int module_install_dso(void *); +extern int module_abandon_dso(void); + +extern int __subsystem_register_module(subsystem_t *, module_base_t *); + +/* Macro to allow polymorphism on module classes */ +#define subsystem_register_module(name, module) \ +({ \ + module_base_t *base = (module_base_t *)module; \ + __subsystem_register_module(&subsystem(name), base); \ +}) + +#endif diff --git a/modular-framework/rwlock.h b/modular-framework/rwlock.h new file mode 100644 index 00000000..108a35b2 --- /dev/null +++ b/modular-framework/rwlock.h @@ -0,0 +1,88 @@ +/* Copyright (c) 2017, ARM Limited. All rights reserved. + * + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RWLOCK_H +#define RWLOCK_H + +/* Get ride on ODP rwlock implementation and in meanwhile + * keep the modular framework as generic as possible, and + * can be re-used in other projects. + * + * Assume that ODP rwlock facility will be available at the + * beginning of the world without any initialization. + */ +#include + +typedef odp_rwlock_t rwlock_t; +#define RW_LOCK_UNLOCKED(lock) ODP_RW_LOCK_UNLOCK(lock) + +#if defined(BUILD_ODP_RWLOCK) + /* only defined in odp rwlock source to link the implementation */ + #define _ALIAS(impl, api) __attribute__((weak, alias(#impl))) api + #define ODP_ALIAS(api) _ALIAS(odp_ ## api, api) +#else + /* other objects only see declarations */ + #define ODP_ALIAS(api) api +#endif + +/** + * Initialize a reader/writer lock. + * + * @param rwlock Pointer to a reader/writer lock + */ +void ODP_ALIAS(rwlock_init)(rwlock_t *rwlock); + +/** + * Acquire read permission on a reader/writer lock. + * + * @param rwlock Pointer to a reader/writer lock + */ +void ODP_ALIAS(rwlock_read_lock)(rwlock_t *rwlock); + +/** + * Try to acquire read permission to a reader/writer lock. + * + * @param rwlock Pointer to a reader/writer lock + * + * @retval 0 Lock was not available for read access + * @retval !0 Read access to lock acquired + */ +int ODP_ALIAS(rwlock_read_trylock)(rwlock_t *rwlock); + +/** + * Release read permission on a reader/writer lock. + * + * @param rwlock Pointer to a reader/writer lock + */ +void ODP_ALIAS(rwlock_read_unlock)(rwlock_t *rwlock); + +/** + * Acquire write permission on a reader/writer lock. + * + * @param rwlock Pointer to a reader/writer lock + */ +void ODP_ALIAS(rwlock_write_lock)(rwlock_t *rwlock); + +/** + * Try to acquire write permission to a reader/writer lock. + * + * @param rwlock Pointer to a reader/writer lock + * + * @retval 0 Lock was not available for write access + * @retval !0 Write access to lock acquired + */ +int ODP_ALIAS(rwlock_write_trylock)(rwlock_t *rwlock); + +/** + * Release write permission on a reader/writer lock. + * + * @param rwlock Pointer to a reader/writer lock + */ +void ODP_ALIAS(rwlock_write_unlock)(rwlock_t *rwlock); + +#endif /* RWLOCK_H */ diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index ba4a31ea..3fc032da 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -6,6 +6,7 @@ include $(top_srcdir)/platform/@with_platform@/Makefile.inc AM_CFLAGS += -I$(srcdir)/include AM_CFLAGS += -I$(top_srcdir)/include +AM_CFLAGS += -I$(top_srcdir)/modular-framework AM_CFLAGS += -I$(top_srcdir)/include/odp/arch/@ARCH_ABI@ AM_CFLAGS += -I$(top_builddir)/include AM_CFLAGS += -Iinclude @@ -292,6 +293,16 @@ if HAVE_PCAP __LIB__libodp_linux_la_SOURCES += pktio/pcap.c endif +modularframeworkdir = $(top_srcdir)/modular-framework +noinst_HEADERS += $(modularframeworkdir)/list.h \ + $(modularframeworkdir)/rwlock.h \ + $(modularframeworkdir)/module.h + +__LIB__libodp_linux_la_SOURCES += ../../modular-framework/module.c + +odp_rwlock.o odp_rwlock.lo : \ + CFLAGS += -DBUILD_ODP_RWLOCK -include $(modularframeworkdir)/rwlock.h + __LIB__libodp_linux_la_LIBADD = $(ATOMIC_LIBS) # Create symlink for ABI header files. Application does not need to use the arch diff --git a/platform/linux-generic/include/odp/api/plat/atomic_types.h b/platform/linux-generic/include/odp/api/plat/atomic_types.h index a674ac99..86c9e5b0 100644 --- a/platform/linux-generic/include/odp/api/plat/atomic_types.h +++ b/platform/linux-generic/include/odp/api/plat/atomic_types.h @@ -81,6 +81,8 @@ typedef struct odp_atomic_u64_s odp_atomic_u64_t; typedef struct odp_atomic_u32_s odp_atomic_u32_t; +#define ODP_ATOMIC_INIT(a) { .v = a } + #ifdef __cplusplus } #endif diff --git a/platform/linux-generic/include/odp/api/plat/rwlock_types.h b/platform/linux-generic/include/odp/api/plat/rwlock_types.h index f7dc0449..a69a5f00 100644 --- a/platform/linux-generic/include/odp/api/plat/rwlock_types.h +++ b/platform/linux-generic/include/odp/api/plat/rwlock_types.h @@ -30,6 +30,8 @@ struct odp_rwlock_s { typedef struct odp_rwlock_s odp_rwlock_t; +#define ODP_RW_LOCK_UNLOCK(lock) { .cnt = ODP_ATOMIC_INIT(0) } + #ifdef __cplusplus } #endif From patchwork Mon Jul 3 08:00:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 106889 Delivered-To: patch@linaro.org Received: by 10.140.101.44 with SMTP id t41csp5489118qge; Mon, 3 Jul 2017 01:06:07 -0700 (PDT) X-Received: by 10.200.54.247 with SMTP id b52mr43042168qtc.145.1499069167213; Mon, 03 Jul 2017 01:06:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1499069167; cv=none; d=google.com; s=arc-20160816; b=mkjqvWmkHELh+CDqYIWA818ueyo6kkPBGOssC77Z3g3I+zbVJhcLuVRjcVbrWsp8TJ 9SsAtbET1wI3RA7vdFDWihO4tjaKVbwvQhMxUmzccRjCKcbE9sdd+ySLFaxN5NMx8KMz i7m/CMX+RnidZGtQ/gKrkfmSYn6idaDqUvGBFAKP0uU6fXiSKQ9H1R5gvdmf98bkLJfO P1mEQH1PwqNogA/x/ekOrbBmcop9XFbmtn6GYDgQKjPF3ixakW2U/SG0g2uSyE5ZD9Xy qEk90sKc44wZhBeqkwvgI6o6qB+tK/HiRhfdSIabXSzqciebJBJo/pQ/F88RrTP8+UZY O2Jg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:github-pr-num :references:in-reply-to:message-id:date:to:from:delivered-to :arc-authentication-results; bh=rcyjbzlPe5Mq0rgQmhCL+/egF13uAF1vDmfJTG7s93E=; b=Qqc/kUH2zImWzVpEjSL5TUZ9ZuZAuBWiTzTD2Vm9/aqcNxPhTWsx1NxGda2hVJ+E32 zgGcDwVPVpRSpHv/JVS335ib6zeYG/t9MZhHIYTKYYRBAQlh0GhtaO8qfA39EmPVicCx XTteGUranHp9Dt91+27x9YLt2GfYUclcXh30coyX+PdSo0nj3I1jnttIAWftCNhP++9a CE9qdfWNj3yqu4y86J9gYBQO3BKRNYRJV+VisIfQEx86cCNHEYD5ZJP8Xq4YRllEEW2O PukQ4x2yi+W8Dvk855vcQ+w1qQc3JjSY/eXX4OSodov3GGllM9c0OqWyebbFaQRaZzmC CEtg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id k124si14096401qkd.259.2017.07.03.01.06.06; Mon, 03 Jul 2017 01:06:07 -0700 (PDT) Received-SPF: pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Received: by lists.linaro.org (Postfix, from userid 109) id CA3E960A52; Mon, 3 Jul 2017 08:06:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, URIBL_BLOCKED, URIBL_SBL, URIBL_SBL_A autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id A562560A6F; Mon, 3 Jul 2017 08:01:17 +0000 (UTC) X-Original-To: lng-odp@lists.linaro.org Delivered-To: lng-odp@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id A707B609F8; Mon, 3 Jul 2017 08:00:42 +0000 (UTC) Received: from forward5h.cmail.yandex.net (forward5h.cmail.yandex.net [87.250.230.20]) by lists.linaro.org (Postfix) with ESMTPS id 5FC87608B8 for ; Mon, 3 Jul 2017 08:00:20 +0000 (UTC) Received: from smtp2m.mail.yandex.net (smtp2m.mail.yandex.net [IPv6:2a02:6b8:0:2519::122]) by forward5h.cmail.yandex.net (Yandex) with ESMTP id D649820BFD for ; Mon, 3 Jul 2017 11:00:18 +0300 (MSK) Received: from smtp2m.mail.yandex.net (localhost.localdomain [127.0.0.1]) by smtp2m.mail.yandex.net (Yandex) with ESMTP id A72992300DF4 for ; Mon, 3 Jul 2017 11:00:18 +0300 (MSK) Received: by smtp2m.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id CsmfCNkM5d-0HNeKkTe; Mon, 03 Jul 2017 11:00:17 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (Client certificate not present) X-Yandex-Suid-Status: 1 0 From: Github ODP bot To: lng-odp@lists.linaro.org Date: Mon, 3 Jul 2017 11:00:09 +0300 Message-Id: <1499068809-20327-3-git-send-email-odpbot@yandex.ru> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1499068809-20327-1-git-send-email-odpbot@yandex.ru> References: <1499068809-20327-1-git-send-email-odpbot@yandex.ru> Github-pr-num: 65 Subject: [lng-odp] [PATCH CLOUD-DEV v1] [RFC 2/2] platform: pktio_ops: apply modular framework X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "The OpenDataPlane \(ODP\) List" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: lng-odp-bounces@lists.linaro.org Sender: "lng-odp" From: Yi He Apply modular programming framework to odp pktio ops subsystem and convert all pktio ops implementation into modules. Signed-off-by: Yi He --- /** Email created from pull request 65 (heyi-linaro:modular-framework) ** https://github.com/Linaro/odp/pull/65 ** Patch: https://github.com/Linaro/odp/pull/65.patch ** Base sha: 1ba26aa5650c05718c177842178de6d0f70b7fc1 ** Merge commit sha: f0f96a26d22e16b9299777cd413dfd6ae89a024e **/ platform/linux-generic/Makefile.am | 15 +- .../linux-generic/include/odp_packet_io_internal.h | 139 +-------------- .../{odp_packet_dpdk.h => odp_pktio_ops_dpdk.h} | 6 +- ...acket_io_ipc_internal.h => odp_pktio_ops_ipc.h} | 42 +++++ .../linux-generic/include/odp_pktio_ops_loopback.h | 17 ++ ...{odp_packet_netmap.h => odp_pktio_ops_netmap.h} | 6 +- .../linux-generic/include/odp_pktio_ops_pcap.h | 25 +++ ...{odp_packet_socket.h => odp_pktio_ops_socket.h} | 8 +- .../include/odp_pktio_ops_subsystem.h | 109 ++++++++++++ .../{odp_packet_tap.h => odp_pktio_ops_tap.h} | 6 +- platform/linux-generic/odp_packet_io.c | 64 ++----- platform/linux-generic/pktio/ethtool.c | 2 +- platform/linux-generic/pktio/io_ops.c | 31 ---- platform/linux-generic/pktio/ipc.c | 195 +++++++++++---------- platform/linux-generic/pktio/loop.c | 36 ++-- platform/linux-generic/pktio/ops_subsystem.c | 19 ++ platform/linux-generic/pktio/pcap.c | 46 +++-- platform/linux-generic/pktio/socket.c | 71 ++++---- platform/linux-generic/pktio/socket_mmap.c | 180 ++++++++++--------- platform/linux-generic/pktio/tap.c | 76 ++++---- 20 files changed, 595 insertions(+), 498 deletions(-) rename platform/linux-generic/include/{odp_packet_dpdk.h => odp_pktio_ops_dpdk.h} (96%) rename platform/linux-generic/include/{odp_packet_io_ipc_internal.h => odp_pktio_ops_ipc.h} (51%) create mode 100644 platform/linux-generic/include/odp_pktio_ops_loopback.h rename platform/linux-generic/include/{odp_packet_netmap.h => odp_pktio_ops_netmap.h} (96%) create mode 100644 platform/linux-generic/include/odp_pktio_ops_pcap.h rename platform/linux-generic/include/{odp_packet_socket.h => odp_pktio_ops_socket.h} (97%) create mode 100644 platform/linux-generic/include/odp_pktio_ops_subsystem.h rename platform/linux-generic/include/{odp_packet_tap.h => odp_pktio_ops_tap.h} (85%) delete mode 100644 platform/linux-generic/pktio/io_ops.c create mode 100644 platform/linux-generic/pktio/ops_subsystem.c diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 3fc032da..7d9da2e7 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -174,13 +174,16 @@ noinst_HEADERS = \ ${srcdir}/include/odp_name_table_internal.h \ ${srcdir}/include/odp_packet_internal.h \ ${srcdir}/include/odp_packet_io_internal.h \ - ${srcdir}/include/odp_packet_io_ipc_internal.h \ ${srcdir}/include/odp_packet_io_queue.h \ ${srcdir}/include/odp_packet_io_ring_internal.h \ - ${srcdir}/include/odp_packet_netmap.h \ - ${srcdir}/include/odp_packet_dpdk.h \ - ${srcdir}/include/odp_packet_socket.h \ - ${srcdir}/include/odp_packet_tap.h \ + ${srcdir}/include/odp_pktio_ops_subsystem.h \ + ${srcdir}/include/odp_pktio_ops_dpdk.h \ + ${srcdir}/include/odp_pktio_ops_ipc.h \ + ${srcdir}/include/odp_pktio_ops_loopback.h \ + ${srcdir}/include/odp_pktio_ops_netmap.h \ + ${srcdir}/include/odp_pktio_ops_pcap.h \ + ${srcdir}/include/odp_pktio_ops_socket.h \ + ${srcdir}/include/odp_pktio_ops_tap.h \ ${srcdir}/include/odp_pkt_queue_internal.h \ ${srcdir}/include/odp_pool_internal.h \ ${srcdir}/include/odp_posix_extensions.h \ @@ -228,7 +231,7 @@ __LIB__libodp_linux_la_SOURCES = \ odp_packet_flags.c \ odp_packet_io.c \ pktio/ethtool.c \ - pktio/io_ops.c \ + pktio/ops_subsystem.c \ pktio/ipc.c \ pktio/pktio_common.c \ pktio/loop.c \ diff --git a/platform/linux-generic/include/odp_packet_io_internal.h b/platform/linux-generic/include/odp_packet_io_internal.h index 89bb6f3a..456f51e6 100644 --- a/platform/linux-generic/include/odp_packet_io_internal.h +++ b/platform/linux-generic/include/odp_packet_io_internal.h @@ -4,7 +4,6 @@ * SPDX-License-Identifier: BSD-3-Clause */ - /** * @file * @@ -23,109 +22,33 @@ extern "C" { #include #include #include -#include - #include #include -#include #define PKTIO_MAX_QUEUES 64 -#include -#include -#include -#include - #define PKTIO_NAME_LEN 256 #define PKTIN_INVALID ((odp_pktin_queue_t) {ODP_PKTIO_INVALID, 0}) #define PKTOUT_INVALID ((odp_pktout_queue_t) {ODP_PKTIO_INVALID, 0}) +/* Forward declaration */ +typedef union pktio_entry_un pktio_entry_t; +#include + /** Determine if a socket read/write error should be reported. Transient errors * that simply require the caller to retry are ignored, the _send/_recv APIs * are non-blocking and it is the caller's responsibility to retry if the * requested number of packets were not handled. */ #define SOCK_ERR_REPORT(e) (e != EAGAIN && e != EWOULDBLOCK && e != EINTR) -/* Forward declaration */ -struct pktio_if_ops; - -typedef struct { - odp_queue_t loopq; /**< loopback queue for "loop" device */ - odp_bool_t promisc; /**< promiscuous mode state */ -} pkt_loop_t; - -#ifdef HAVE_PCAP -typedef struct { - char *fname_rx; /**< name of pcap file for rx */ - char *fname_tx; /**< name of pcap file for tx */ - void *rx; /**< rx pcap handle */ - void *tx; /**< tx pcap handle */ - void *tx_dump; /**< tx pcap dumper handle */ - odp_pool_t pool; /**< rx pool */ - unsigned char *buf; /**< per-pktio temp buffer */ - int loops; /**< number of times to loop rx pcap */ - int loop_cnt; /**< number of loops completed */ - odp_bool_t promisc; /**< promiscuous mode state */ -} pkt_pcap_t; -#endif - -typedef struct { - /* TX */ - struct { - _ring_t *send; /**< ODP ring for IPC msg packets - indexes transmitted to shared - memory */ - _ring_t *free; /**< ODP ring for IPC msg packets - indexes already processed by remote - process */ - } tx; - /* RX */ - struct { - _ring_t *recv; /**< ODP ring for IPC msg packets - indexes received from shared - memory (from remote process) */ - _ring_t *free; /**< ODP ring for IPC msg packets - indexes already processed by - current process */ - } rx; /* slave */ - void *pool_base; /**< Remote pool base addr */ - void *pool_mdata_base; /**< Remote pool mdata base addr */ - uint64_t pkt_size; /**< Packet size in remote pool */ - odp_pool_t pool; /**< Pool of main process */ - enum { - PKTIO_TYPE_IPC_MASTER = 0, /**< Master is the process which - creates shm */ - PKTIO_TYPE_IPC_SLAVE /**< Slave is the process which - connects to shm */ - } type; /**< define if it's master or slave process */ - odp_atomic_u32_t ready; /**< 1 - pktio is ready and can recv/send - packet, 0 - not yet ready */ - void *pinfo; - odp_shm_t pinfo_shm; - odp_shm_t remote_pool_shm; /**< shm of remote pool get with - _ipc_map_remote_pool() */ -} _ipc_pktio_t; - struct pktio_entry { - const struct pktio_if_ops *ops; /**< Implementation specific methods */ + const pktio_ops_module_t *ops; /**< Implementation specific methods */ + pktio_ops_data_t ops_data; /**< IO operation specific data */ /* These two locks together lock the whole pktio device */ odp_ticketlock_t rxl; /**< RX ticketlock */ odp_ticketlock_t txl; /**< TX ticketlock */ int cls_enabled; /**< is classifier enabled */ odp_pktio_t handle; /**< pktio handle */ - union { - pkt_loop_t pkt_loop; /**< Using loopback for IO */ - pkt_sock_t pkt_sock; /**< using socket API for IO */ - pkt_sock_mmap_t pkt_sock_mmap; /**< using socket mmap - * API for IO */ - pkt_netmap_t pkt_nm; /**< using netmap API for IO */ - pkt_dpdk_t pkt_dpdk; /**< using DPDK for IO */ -#ifdef HAVE_PCAP - pkt_pcap_t pkt_pcap; /**< Using pcap for IO */ -#endif - pkt_tap_t pkt_tap; /**< using TAP for IO */ - _ipc_pktio_t ipc; /**< IPC pktio data */ - }; enum { /* Not allocated */ PKTIO_STATE_FREE = 0, @@ -174,50 +97,16 @@ struct pktio_entry { } out_queue[PKTIO_MAX_QUEUES]; }; -typedef union { +union pktio_entry_un { struct pktio_entry s; uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(struct pktio_entry))]; -} pktio_entry_t; +}; typedef struct { odp_spinlock_t lock; pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES]; } pktio_table_t; -typedef struct pktio_if_ops { - const char *name; - void (*print)(pktio_entry_t *pktio_entry); - int (*init_global)(void); - int (*init_local)(void); - int (*term)(void); - int (*open)(odp_pktio_t pktio, pktio_entry_t *pktio_entry, - const char *devname, odp_pool_t pool); - int (*close)(pktio_entry_t *pktio_entry); - int (*start)(pktio_entry_t *pktio_entry); - int (*stop)(pktio_entry_t *pktio_entry); - int (*stats)(pktio_entry_t *pktio_entry, odp_pktio_stats_t *stats); - int (*stats_reset)(pktio_entry_t *pktio_entry); - uint64_t (*pktin_ts_res)(pktio_entry_t *pktio_entry); - odp_time_t (*pktin_ts_from_ns)(pktio_entry_t *pktio_entry, uint64_t ns); - int (*recv)(pktio_entry_t *entry, int index, odp_packet_t packets[], - int num); - int (*send)(pktio_entry_t *entry, int index, - const odp_packet_t packets[], int num); - uint32_t (*mtu_get)(pktio_entry_t *pktio_entry); - int (*promisc_mode_set)(pktio_entry_t *pktio_entry, int enable); - int (*promisc_mode_get)(pktio_entry_t *pktio_entry); - int (*mac_get)(pktio_entry_t *pktio_entry, void *mac_addr); - int (*link_status)(pktio_entry_t *pktio_entry); - int (*capability)(pktio_entry_t *pktio_entry, - odp_pktio_capability_t *capa); - int (*config)(pktio_entry_t *pktio_entry, - const odp_pktio_config_t *config); - int (*input_queues_config)(pktio_entry_t *pktio_entry, - const odp_pktin_queue_param_t *param); - int (*output_queues_config)(pktio_entry_t *pktio_entry, - const odp_pktout_queue_param_t *p); -} pktio_if_ops_t; - extern void *pktio_entry_ptr[]; static inline int pktio_to_id(odp_pktio_t pktio) @@ -262,18 +151,6 @@ int single_recv_queue(pktio_entry_t *entry, int index, odp_packet_t packets[], int single_send_queue(pktio_entry_t *entry, int index, const odp_packet_t packets[], int num); -extern const pktio_if_ops_t netmap_pktio_ops; -extern const pktio_if_ops_t dpdk_pktio_ops; -extern const pktio_if_ops_t sock_mmsg_pktio_ops; -extern const pktio_if_ops_t sock_mmap_pktio_ops; -extern const pktio_if_ops_t loopback_pktio_ops; -#ifdef HAVE_PCAP -extern const pktio_if_ops_t pcap_pktio_ops; -#endif -extern const pktio_if_ops_t tap_pktio_ops; -extern const pktio_if_ops_t ipc_pktio_ops; -extern const pktio_if_ops_t * const pktio_if_ops[]; - int sysfs_stats(pktio_entry_t *pktio_entry, odp_pktio_stats_t *stats); int sock_stats_fd(pktio_entry_t *pktio_entry, diff --git a/platform/linux-generic/include/odp_packet_dpdk.h b/platform/linux-generic/include/odp_pktio_ops_dpdk.h similarity index 96% rename from platform/linux-generic/include/odp_packet_dpdk.h rename to platform/linux-generic/include/odp_pktio_ops_dpdk.h index 4d7e0fc4..61c96d55 100644 --- a/platform/linux-generic/include/odp_packet_dpdk.h +++ b/platform/linux-generic/include/odp_pktio_ops_dpdk.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef ODP_PACKET_DPDK_H -#define ODP_PACKET_DPDK_H +#ifndef ODP_PKTIO_OPS_DPDK_H +#define ODP_PKTIO_OPS_DPDK_H #include #include @@ -65,6 +65,6 @@ typedef struct { odp_ticketlock_t tx_lock[PKTIO_MAX_QUEUES]; /**< TX queue locks */ /** cache for storing extra RX packets */ pkt_cache_t rx_cache[PKTIO_MAX_QUEUES]; -} pkt_dpdk_t; +} pktio_ops_dpdk_data_t; #endif diff --git a/platform/linux-generic/include/odp_packet_io_ipc_internal.h b/platform/linux-generic/include/odp_pktio_ops_ipc.h similarity index 51% rename from platform/linux-generic/include/odp_packet_io_ipc_internal.h rename to platform/linux-generic/include/odp_pktio_ops_ipc.h index 7cd29488..ba302ca7 100644 --- a/platform/linux-generic/include/odp_packet_io_ipc_internal.h +++ b/platform/linux-generic/include/odp_pktio_ops_ipc.h @@ -4,6 +4,9 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#ifndef ODP_PKTIO_OPS_IPC_H +#define ODP_PKTIO_OPS_IPC_H + #include #include #include @@ -54,3 +57,42 @@ struct pktio_info { int init_done; } slave; } ODP_PACKED; + +typedef struct { + /* TX */ + struct { + _ring_t *send; /**< ODP ring for IPC msg packets + indexes transmitted to shared + memory */ + _ring_t *free; /**< ODP ring for IPC msg packets + indexes already processed by remote + process */ + } tx; + /* RX */ + struct { + _ring_t *recv; /**< ODP ring for IPC msg packets + indexes received from shared + memory (from remote process) */ + _ring_t *free; /**< ODP ring for IPC msg packets + indexes already processed by + current process */ + } rx; /* slave */ + void *pool_base; /**< Remote pool base addr */ + void *pool_mdata_base; /**< Remote pool mdata base addr */ + uint64_t pkt_size; /**< Packet size in remote pool */ + odp_pool_t pool; /**< Pool of main process */ + enum { + PKTIO_TYPE_IPC_MASTER = 0, /**< Master is the process which + creates shm */ + PKTIO_TYPE_IPC_SLAVE /**< Slave is the process which + connects to shm */ + } type; /**< define if it's master or slave process */ + odp_atomic_u32_t ready; /**< 1 - pktio is ready and can recv/send + packet, 0 - not yet ready */ + void *pinfo; + odp_shm_t pinfo_shm; + odp_shm_t remote_pool_shm; /**< shm of remote pool get with + _ipc_map_remote_pool() */ +} pktio_ops_ipc_data_t; + +#endif diff --git a/platform/linux-generic/include/odp_pktio_ops_loopback.h b/platform/linux-generic/include/odp_pktio_ops_loopback.h new file mode 100644 index 00000000..6b58f8e4 --- /dev/null +++ b/platform/linux-generic/include/odp_pktio_ops_loopback.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2017, ARM Limited. All rights reserved. + * + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_PKTIO_OPS_LOOPBACK_H +#define ODP_PKTIO_OPS_LOOPBACK_H + +typedef struct { + odp_queue_t loopq; /**< loopback queue for "loop" device */ + odp_bool_t promisc; /**< promiscuous mode state */ +} pktio_ops_loopback_data_t; + +#endif diff --git a/platform/linux-generic/include/odp_packet_netmap.h b/platform/linux-generic/include/odp_pktio_ops_netmap.h similarity index 96% rename from platform/linux-generic/include/odp_packet_netmap.h rename to platform/linux-generic/include/odp_pktio_ops_netmap.h index a6f68d56..4f36eaa7 100644 --- a/platform/linux-generic/include/odp_packet_netmap.h +++ b/platform/linux-generic/include/odp_pktio_ops_netmap.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef ODP_PACKET_NETMAP_H -#define ODP_PACKET_NETMAP_H +#ifndef ODP_PKTIO_OPS_NETMAP_H +#define ODP_PKTIO_OPS_NETMAP_H #include #include @@ -63,6 +63,6 @@ typedef struct { netmap_ring_t rx_desc_ring[PKTIO_MAX_QUEUES]; /** mapping of pktout queues to netmap tx descriptors */ netmap_ring_t tx_desc_ring[PKTIO_MAX_QUEUES]; -} pkt_netmap_t; +} pktio_ops_netmap_data_t; #endif diff --git a/platform/linux-generic/include/odp_pktio_ops_pcap.h b/platform/linux-generic/include/odp_pktio_ops_pcap.h new file mode 100644 index 00000000..80c979c1 --- /dev/null +++ b/platform/linux-generic/include/odp_pktio_ops_pcap.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2017, ARM Limited. All rights reserved. + * + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_PKTIO_OPS_PCAP_H +#define ODP_PKTIO_OPS_PCAP_H + +typedef struct { + char *fname_rx; /**< name of pcap file for rx */ + char *fname_tx; /**< name of pcap file for tx */ + void *rx; /**< rx pcap handle */ + void *tx; /**< tx pcap handle */ + void *tx_dump; /**< tx pcap dumper handle */ + odp_pool_t pool; /**< rx pool */ + unsigned char *buf; /**< per-pktio temp buffer */ + int loops; /**< number of times to loop rx pcap */ + int loop_cnt; /**< number of loops completed */ + odp_bool_t promisc; /**< promiscuous mode state */ +} pktio_ops_pcap_data_t; + +#endif diff --git a/platform/linux-generic/include/odp_packet_socket.h b/platform/linux-generic/include/odp_pktio_ops_socket.h similarity index 97% rename from platform/linux-generic/include/odp_packet_socket.h rename to platform/linux-generic/include/odp_pktio_ops_socket.h index 0e61f6f0..7c97f03d 100644 --- a/platform/linux-generic/include/odp_packet_socket.h +++ b/platform/linux-generic/include/odp_pktio_ops_socket.h @@ -5,8 +5,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef ODP_PACKET_SOCKET_H -#define ODP_PACKET_SOCKET_H +#ifndef ODP_PKTIO_OPS_SOCKET_H +#define ODP_PKTIO_OPS_SOCKET_H #include #include @@ -42,7 +42,7 @@ typedef struct { odp_pool_t pool; /**< pool to alloc packets from */ uint32_t mtu; /**< maximum transmission unit */ unsigned char if_mac[ETH_ALEN]; /**< IF eth mac addr */ -} pkt_sock_t; +} pktio_ops_socket_data_t; /** packet mmap ring */ struct ring { @@ -79,7 +79,7 @@ typedef struct { unsigned char if_mac[ETH_ALEN]; struct sockaddr_ll ll; int fanout; -} pkt_sock_mmap_t; +} pktio_ops_socket_mmap_data_t; static inline void ethaddr_copy(unsigned char mac_dst[], unsigned char mac_src[]) diff --git a/platform/linux-generic/include/odp_pktio_ops_subsystem.h b/platform/linux-generic/include/odp_pktio_ops_subsystem.h new file mode 100644 index 00000000..cdaeb2cf --- /dev/null +++ b/platform/linux-generic/include/odp_pktio_ops_subsystem.h @@ -0,0 +1,109 @@ +/* Copyright (c) 2017, ARM Limited. All rights reserved. + * + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_SUBSYSTEM_PKTIO_OPS_H +#define ODP_SUBSYSTEM_PKTIO_OPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* ODP packet IO operations subsystem declaration */ +extern SUBSYSTEM(pktio_ops); + +/* Subsystem APIs declarations */ +SUBSYSTEM_API(pktio_ops, int, open, odp_pktio_t, + pktio_entry_t *, const char *, odp_pool_t); +SUBSYSTEM_API(pktio_ops, int, close, pktio_entry_t *); +SUBSYSTEM_API(pktio_ops, int, start, pktio_entry_t *); +SUBSYSTEM_API(pktio_ops, int, stop, pktio_entry_t *); +SUBSYSTEM_API(pktio_ops, int, stats, pktio_entry_t *, + odp_pktio_stats_t *stats); +SUBSYSTEM_API(pktio_ops, int, stats_reset, pktio_entry_t *); +SUBSYSTEM_API(pktio_ops, uint64_t, pktin_ts_res, pktio_entry_t *); +SUBSYSTEM_API(pktio_ops, odp_time_t, pktin_ts_from_ns, + pktio_entry_t *, uint64_t ns); +SUBSYSTEM_API(pktio_ops, int, recv, pktio_entry_t *, + int index, odp_packet_t packets[], int count); +SUBSYSTEM_API(pktio_ops, int, send, pktio_entry_t *, + int index, const odp_packet_t packets[], int count); +SUBSYSTEM_API(pktio_ops, uint32_t, mtu_get, pktio_entry_t *); +SUBSYSTEM_API(pktio_ops, int, promisc_mode_set, + pktio_entry_t *, int enable); +SUBSYSTEM_API(pktio_ops, int, promisc_mode_get, pktio_entry_t *); +SUBSYSTEM_API(pktio_ops, int, mac_get, pktio_entry_t *, void *); +SUBSYSTEM_API(pktio_ops, int, link_status, pktio_entry_t *); +SUBSYSTEM_API(pktio_ops, int, capability, pktio_entry_t *, + odp_pktio_capability_t *); +SUBSYSTEM_API(pktio_ops, int, config, pktio_entry_t *, + const odp_pktio_config_t *); +SUBSYSTEM_API(pktio_ops, int, input_queues_config, + pktio_entry_t *, const odp_pktin_queue_param_t *); +SUBSYSTEM_API(pktio_ops, int, output_queues_config, + pktio_entry_t *, const odp_pktout_queue_param_t *); +SUBSYSTEM_API(pktio_ops, void, print, pktio_entry_t *); + +typedef MODULE_CLASS(pktio_ops) + api_proto(pktio_ops, open) open; + api_proto(pktio_ops, close) close; + api_proto(pktio_ops, start) start; + api_proto(pktio_ops, stop) stop; + api_proto(pktio_ops, stats) stats; + api_proto(pktio_ops, stats_reset) stats_reset; + api_proto(pktio_ops, pktin_ts_res) pktin_ts_res; + api_proto(pktio_ops, pktin_ts_from_ns) pktin_ts_from_ns; + api_proto(pktio_ops, recv) recv; + api_proto(pktio_ops, send) send; + api_proto(pktio_ops, mtu_get) mtu_get; + api_proto(pktio_ops, promisc_mode_set) promisc_mode_set; + api_proto(pktio_ops, promisc_mode_get) promisc_mode_get; + api_proto(pktio_ops, mac_get) mac_get; + api_proto(pktio_ops, link_status) link_status; + api_proto(pktio_ops, capability) capability; + api_proto(pktio_ops, config) config; + api_proto(pktio_ops, input_queues_config) input_queues_config; + api_proto(pktio_ops, output_queues_config) output_queues_config; + api_proto(pktio_ops, print) print; +} pktio_ops_module_t; + +/* All implementations of this subsystem */ +#include +#include +#include +#include +#ifdef HAVE_PCAP +#include +#endif +#include +#include + +/* Per pktio instance data used by each implementation */ +typedef union { + pktio_ops_dpdk_data_t dpdk; + pktio_ops_ipc_data_t ipc; + pktio_ops_loopback_data_t loopback; + pktio_ops_netmap_data_t netmap; +#ifdef HAVE_PCAP + pktio_ops_pcap_data_t pcap; +#endif + pktio_ops_socket_data_t _socket; + pktio_ops_socket_mmap_data_t _mmap; + pktio_ops_tap_data_t tap; +} pktio_ops_data_t; + +/* Extract pktio ops data from pktio entry structure */ +#define ops_data(mod) s.ops_data.mod + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/include/odp_packet_tap.h b/platform/linux-generic/include/odp_pktio_ops_tap.h similarity index 85% rename from platform/linux-generic/include/odp_packet_tap.h rename to platform/linux-generic/include/odp_pktio_ops_tap.h index a90bfbce..1cbc31cf 100644 --- a/platform/linux-generic/include/odp_packet_tap.h +++ b/platform/linux-generic/include/odp_pktio_ops_tap.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef ODP_PACKET_TAP_H_ -#define ODP_PACKET_TAP_H_ +#ifndef ODP_PACKET_OPS_TAP_H +#define ODP_PACKET_OPS_TAP_H #include @@ -16,6 +16,6 @@ typedef struct { unsigned char if_mac[ETH_ALEN]; /**< MAC address of pktio side (not a MAC address of kernel interface)*/ odp_pool_t pool; /**< pool to alloc packets from */ -} pkt_tap_t; +} pktio_ops_tap_data_t; #endif diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c index 4dd28549..45124567 100644 --- a/platform/linux-generic/odp_packet_io.c +++ b/platform/linux-generic/odp_packet_io.c @@ -14,13 +14,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include @@ -47,12 +45,14 @@ static inline pktio_entry_t *pktio_entry_by_index(int index) return pktio_entry_ptr[index]; } +SUBSYSTEM_INITERM_TEMPLATE(pktio_ops, init_local, ODP_ERR) +SUBSYSTEM_INITERM_TEMPLATE(pktio_ops, init_global, ODP_ERR) + int odp_pktio_init_global(void) { pktio_entry_t *pktio_entry; int i; odp_shm_t shm; - int pktio_if; shm = odp_shm_reserve("odp_pktio_entries", sizeof(pktio_table_t), @@ -77,33 +77,11 @@ int odp_pktio_init_global(void) pktio_entry_ptr[i] = pktio_entry; } - for (pktio_if = 0; pktio_if_ops[pktio_if]; ++pktio_if) { - if (pktio_if_ops[pktio_if]->init_global) - if (pktio_if_ops[pktio_if]->init_global()) { - ODP_ERR("failed to initialized pktio type %d", - pktio_if); - return -1; - } - } - - return 0; + return pktio_ops_subsystem_init_global(); } -int odp_pktio_init_local(void) -{ - int pktio_if; - - for (pktio_if = 0; pktio_if_ops[pktio_if]; ++pktio_if) { - if (pktio_if_ops[pktio_if]->init_local) - if (pktio_if_ops[pktio_if]->init_local()) { - ODP_ERR("failed to initialized pktio type %d", - pktio_if); - return -1; - } - } - - return 0; -} +int __attribute__((alias("pktio_ops_subsystem_init_local"))) + odp_pktio_init_local(void); static inline int is_free(pktio_entry_t *entry) { @@ -181,8 +159,7 @@ static odp_pktio_t setup_pktio_entry(const char *name, odp_pool_t pool, { odp_pktio_t hdl; pktio_entry_t *pktio_entry; - int ret = -1; - int pktio_if; + pktio_ops_module_t *mod; if (strlen(name) >= PKTIO_NAME_LEN - 1) { /* ioctl names limitation */ @@ -208,19 +185,18 @@ static odp_pktio_t setup_pktio_entry(const char *name, odp_pool_t pool, odp_pktio_config_init(&pktio_entry->s.config); - for (pktio_if = 0; pktio_if_ops[pktio_if]; ++pktio_if) { - ret = pktio_if_ops[pktio_if]->open(hdl, pktio_entry, name, - pool); - - if (!ret) { - pktio_entry->s.ops = pktio_if_ops[pktio_if]; - ODP_DBG("%s uses %s\n", - name, pktio_if_ops[pktio_if]->name); + subsystem_lock(read, pktio_ops); + subsystem_foreach_module(pktio_ops, mod) { + if (mod->open != NULL && + mod->open(hdl, pktio_entry, name, pool)) { + pktio_entry->s.ops = mod; + ODP_DBG("%s uses %s\n", name, mod->name); break; } } + subsystem_unlock(read, pktio_ops); - if (ret != 0) { + if (pktio_entry->s.ops == NULL) { pktio_entry->s.state = PKTIO_STATE_FREE; hdl = ODP_PKTIO_INVALID; ODP_ERR("Unable to init any I/O type.\n"); @@ -1060,11 +1036,12 @@ void odp_pktio_print(odp_pktio_t hdl) ODP_PRINT("\n"); } +SUBSYSTEM_INITERM_TEMPLATE(pktio_ops, term_global, ODP_ABORT) + int odp_pktio_term_global(void) { int ret = 0; int i; - int pktio_if; for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) { pktio_entry_t *pktio_entry; @@ -1090,12 +1067,7 @@ int odp_pktio_term_global(void) unlock_entry(pktio_entry); } - for (pktio_if = 0; pktio_if_ops[pktio_if]; ++pktio_if) { - if (pktio_if_ops[pktio_if]->term) - if (pktio_if_ops[pktio_if]->term()) - ODP_ABORT("failed to terminate pktio type %d", - pktio_if); - } + ret = pktio_ops_subsystem_term_global(); ret = odp_shm_free(odp_shm_lookup("odp_pktio_entries")); if (ret != 0) diff --git a/platform/linux-generic/pktio/ethtool.c b/platform/linux-generic/pktio/ethtool.c index d8f9e12c..de35fd9c 100644 --- a/platform/linux-generic/pktio/ethtool.c +++ b/platform/linux-generic/pktio/ethtool.c @@ -13,7 +13,7 @@ #include #include -#include +#include #include static struct ethtool_gstrings *get_stringset(int fd, struct ifreq *ifr) diff --git a/platform/linux-generic/pktio/io_ops.c b/platform/linux-generic/pktio/io_ops.c deleted file mode 100644 index fbf30ca7..00000000 --- a/platform/linux-generic/pktio/io_ops.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (c) 2013, Linaro Limited - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include - -/* Ops for all implementation of pktio. - * Order matters. The first implementation to setup successfully - * will be picked. - * Array must be NULL terminated */ -const pktio_if_ops_t * const pktio_if_ops[] = { - &loopback_pktio_ops, -#ifdef ODP_PKTIO_DPDK - &dpdk_pktio_ops, -#endif -#ifdef ODP_NETMAP - &netmap_pktio_ops, -#endif -#ifdef HAVE_PCAP - &pcap_pktio_ops, -#endif -#ifdef _ODP_PKTIO_IPC - &ipc_pktio_ops, -#endif - &tap_pktio_ops, - &sock_mmap_pktio_ops, - &sock_mmsg_pktio_ops, - NULL -}; diff --git a/platform/linux-generic/pktio/ipc.c b/platform/linux-generic/pktio/ipc.c index 06175e5a..5bd5fb95 100644 --- a/platform/linux-generic/pktio/ipc.c +++ b/platform/linux-generic/pktio/ipc.c @@ -3,7 +3,6 @@ * * SPDX-License-Identifier: BSD-3-Clause */ -#include #include #include #include @@ -43,7 +42,7 @@ static const char *_ipc_odp_buffer_pool_shm_name(odp_pool_t pool_hdl) static int _ipc_master_start(pktio_entry_t *pktio_entry) { - struct pktio_info *pinfo = pktio_entry->s.ipc.pinfo; + struct pktio_info *pinfo = pktio_entry->ops_data(ipc).pinfo; odp_shm_t shm; if (pinfo->slave.init_done == 0) @@ -57,12 +56,12 @@ static int _ipc_master_start(pktio_entry_t *pktio_entry) return -1; } - pktio_entry->s.ipc.remote_pool_shm = shm; - pktio_entry->s.ipc.pool_base = odp_shm_addr(shm); - pktio_entry->s.ipc.pool_mdata_base = (char *)odp_shm_addr(shm) + + pktio_entry->ops_data(ipc).remote_pool_shm = shm; + pktio_entry->ops_data(ipc).pool_base = odp_shm_addr(shm); + pktio_entry->ops_data(ipc).pool_mdata_base = (char *)odp_shm_addr(shm) + pinfo->slave.base_addr_offset; - odp_atomic_store_u32(&pktio_entry->s.ipc.ready, 1); + odp_atomic_store_u32(&pktio_entry->ops_data(ipc).ready, 1); IPC_ODP_DBG("%s started.\n", pktio_entry->s.name); return 0; @@ -89,62 +88,62 @@ static int _ipc_init_master(pktio_entry_t *pktio_entry, * to be processed packets ring. */ snprintf(ipc_shm_name, sizeof(ipc_shm_name), "%s_m_prod", dev); - pktio_entry->s.ipc.tx.send = _ring_create(ipc_shm_name, + pktio_entry->ops_data(ipc).tx.send = _ring_create(ipc_shm_name, PKTIO_IPC_ENTRIES, _RING_SHM_PROC | _RING_NO_LIST); - if (!pktio_entry->s.ipc.tx.send) { + if (!pktio_entry->ops_data(ipc).tx.send) { ODP_ERR("pid %d unable to create ipc ring %s name\n", getpid(), ipc_shm_name); return -1; } ODP_DBG("Created IPC ring: %s, count %d, free %d\n", - ipc_shm_name, _ring_count(pktio_entry->s.ipc.tx.send), - _ring_free_count(pktio_entry->s.ipc.tx.send)); + ipc_shm_name, _ring_count(pktio_entry->ops_data(ipc).tx.send), + _ring_free_count(pktio_entry->ops_data(ipc).tx.send)); /* generate name in shm like ipc_pktio_p for * already processed packets */ snprintf(ipc_shm_name, sizeof(ipc_shm_name), "%s_m_cons", dev); - pktio_entry->s.ipc.tx.free = _ring_create(ipc_shm_name, + pktio_entry->ops_data(ipc).tx.free = _ring_create(ipc_shm_name, PKTIO_IPC_ENTRIES, _RING_SHM_PROC | _RING_NO_LIST); - if (!pktio_entry->s.ipc.tx.free) { + if (!pktio_entry->ops_data(ipc).tx.free) { ODP_ERR("pid %d unable to create ipc ring %s name\n", getpid(), ipc_shm_name); goto free_m_prod; } ODP_DBG("Created IPC ring: %s, count %d, free %d\n", - ipc_shm_name, _ring_count(pktio_entry->s.ipc.tx.free), - _ring_free_count(pktio_entry->s.ipc.tx.free)); + ipc_shm_name, _ring_count(pktio_entry->ops_data(ipc).tx.free), + _ring_free_count(pktio_entry->ops_data(ipc).tx.free)); snprintf(ipc_shm_name, sizeof(ipc_shm_name), "%s_s_prod", dev); - pktio_entry->s.ipc.rx.recv = _ring_create(ipc_shm_name, + pktio_entry->ops_data(ipc).rx.recv = _ring_create(ipc_shm_name, PKTIO_IPC_ENTRIES, _RING_SHM_PROC | _RING_NO_LIST); - if (!pktio_entry->s.ipc.rx.recv) { + if (!pktio_entry->ops_data(ipc).rx.recv) { ODP_ERR("pid %d unable to create ipc ring %s name\n", getpid(), ipc_shm_name); goto free_m_cons; } ODP_DBG("Created IPC ring: %s, count %d, free %d\n", - ipc_shm_name, _ring_count(pktio_entry->s.ipc.rx.recv), - _ring_free_count(pktio_entry->s.ipc.rx.recv)); + ipc_shm_name, _ring_count(pktio_entry->ops_data(ipc).rx.recv), + _ring_free_count(pktio_entry->ops_data(ipc).rx.recv)); snprintf(ipc_shm_name, sizeof(ipc_shm_name), "%s_s_cons", dev); - pktio_entry->s.ipc.rx.free = _ring_create(ipc_shm_name, + pktio_entry->ops_data(ipc).rx.free = _ring_create(ipc_shm_name, PKTIO_IPC_ENTRIES, _RING_SHM_PROC | _RING_NO_LIST); - if (!pktio_entry->s.ipc.rx.free) { + if (!pktio_entry->ops_data(ipc).rx.free) { ODP_ERR("pid %d unable to create ipc ring %s name\n", getpid(), ipc_shm_name); goto free_s_prod; } ODP_DBG("Created IPC ring: %s, count %d, free %d\n", - ipc_shm_name, _ring_count(pktio_entry->s.ipc.rx.free), - _ring_free_count(pktio_entry->s.ipc.rx.free)); + ipc_shm_name, _ring_count(pktio_entry->ops_data(ipc).rx.free), + _ring_free_count(pktio_entry->ops_data(ipc).rx.free)); /* Set up pool name for remote info */ - pinfo = pktio_entry->s.ipc.pinfo; + pinfo = pktio_entry->ops_data(ipc).pinfo; pool_name = _ipc_odp_buffer_pool_shm_name(pool_hdl); if (strlen(pool_name) > ODP_POOL_NAME_LEN) { ODP_ERR("pid %d ipc pool name %s is too big %d\n", @@ -158,7 +157,7 @@ static int _ipc_init_master(pktio_entry_t *pktio_entry, pinfo->slave.pid = 0; pinfo->slave.init_done = 0; - pktio_entry->s.ipc.pool = pool_hdl; + pktio_entry->ops_data(ipc).pool = pool_hdl; ODP_DBG("Pre init... DONE.\n"); pinfo->master.init_done = 1; @@ -227,7 +226,7 @@ static int _ipc_init_slave(const char *dev, if (strlen(dev) > (ODP_POOL_NAME_LEN - sizeof("_slave_r"))) ODP_ABORT("too big ipc name\n"); - pktio_entry->s.ipc.pool = pool; + pktio_entry->ops_data(ipc).pool = pool; return 0; } @@ -248,62 +247,62 @@ static int _ipc_slave_start(pktio_entry_t *pktio_entry) sprintf(dev, "ipc:%s", tail); snprintf(ipc_shm_name, sizeof(ipc_shm_name), "%s_m_prod", dev); - pktio_entry->s.ipc.rx.recv = _ipc_shm_map(ipc_shm_name, pid); - if (!pktio_entry->s.ipc.rx.recv) { + pktio_entry->ops_data(ipc).rx.recv = _ipc_shm_map(ipc_shm_name, pid); + if (!pktio_entry->ops_data(ipc).rx.recv) { ODP_DBG("pid %d unable to find ipc ring %s name\n", getpid(), dev); sleep(1); return -1; } ODP_DBG("Connected IPC ring: %s, count %d, free %d\n", - ipc_shm_name, _ring_count(pktio_entry->s.ipc.rx.recv), - _ring_free_count(pktio_entry->s.ipc.rx.recv)); + ipc_shm_name, _ring_count(pktio_entry->ops_data(ipc).rx.recv), + _ring_free_count(pktio_entry->ops_data(ipc).rx.recv)); snprintf(ipc_shm_name, sizeof(ipc_shm_name), "%s_m_cons", dev); - pktio_entry->s.ipc.rx.free = _ipc_shm_map(ipc_shm_name, pid); - if (!pktio_entry->s.ipc.rx.free) { + pktio_entry->ops_data(ipc).rx.free = _ipc_shm_map(ipc_shm_name, pid); + if (!pktio_entry->ops_data(ipc).rx.free) { ODP_ERR("pid %d unable to find ipc ring %s name\n", getpid(), dev); goto free_m_prod; } ODP_DBG("Connected IPC ring: %s, count %d, free %d\n", - ipc_shm_name, _ring_count(pktio_entry->s.ipc.rx.free), - _ring_free_count(pktio_entry->s.ipc.rx.free)); + ipc_shm_name, _ring_count(pktio_entry->ops_data(ipc).rx.free), + _ring_free_count(pktio_entry->ops_data(ipc).rx.free)); snprintf(ipc_shm_name, sizeof(ipc_shm_name), "%s_s_prod", dev); - pktio_entry->s.ipc.tx.send = _ipc_shm_map(ipc_shm_name, pid); - if (!pktio_entry->s.ipc.tx.send) { + pktio_entry->ops_data(ipc).tx.send = _ipc_shm_map(ipc_shm_name, pid); + if (!pktio_entry->ops_data(ipc).tx.send) { ODP_ERR("pid %d unable to find ipc ring %s name\n", getpid(), dev); goto free_m_cons; } ODP_DBG("Connected IPC ring: %s, count %d, free %d\n", - ipc_shm_name, _ring_count(pktio_entry->s.ipc.tx.send), - _ring_free_count(pktio_entry->s.ipc.tx.send)); + ipc_shm_name, _ring_count(pktio_entry->ops_data(ipc).tx.send), + _ring_free_count(pktio_entry->ops_data(ipc).tx.send)); snprintf(ipc_shm_name, sizeof(ipc_shm_name), "%s_s_cons", dev); - pktio_entry->s.ipc.tx.free = _ipc_shm_map(ipc_shm_name, pid); - if (!pktio_entry->s.ipc.tx.free) { + pktio_entry->ops_data(ipc).tx.free = _ipc_shm_map(ipc_shm_name, pid); + if (!pktio_entry->ops_data(ipc).tx.free) { ODP_ERR("pid %d unable to find ipc ring %s name\n", getpid(), dev); goto free_s_prod; } ODP_DBG("Connected IPC ring: %s, count %d, free %d\n", - ipc_shm_name, _ring_count(pktio_entry->s.ipc.tx.free), - _ring_free_count(pktio_entry->s.ipc.tx.free)); + ipc_shm_name, _ring_count(pktio_entry->ops_data(ipc).tx.free), + _ring_free_count(pktio_entry->ops_data(ipc).tx.free)); /* Get info about remote pool */ - pinfo = pktio_entry->s.ipc.pinfo; + pinfo = pktio_entry->ops_data(ipc).pinfo; shm = _ipc_map_remote_pool(pinfo->master.pool_name, pid); - pktio_entry->s.ipc.remote_pool_shm = shm; - pktio_entry->s.ipc.pool_mdata_base = (char *)odp_shm_addr(shm) + + pktio_entry->ops_data(ipc).remote_pool_shm = shm; + pktio_entry->ops_data(ipc).pool_mdata_base = (char *)odp_shm_addr(shm) + pinfo->master.base_addr_offset; - pktio_entry->s.ipc.pkt_size = pinfo->master.block_size; + pktio_entry->ops_data(ipc).pkt_size = pinfo->master.block_size; - _ipc_export_pool(pinfo, pktio_entry->s.ipc.pool); + _ipc_export_pool(pinfo, pktio_entry->ops_data(ipc).pool); - odp_atomic_store_u32(&pktio_entry->s.ipc.ready, 1); + odp_atomic_store_u32(&pktio_entry->ops_data(ipc).ready, 1); pinfo->slave.init_done = 1; ODP_DBG("%s started.\n", pktio_entry->s.name); @@ -342,11 +341,11 @@ static int ipc_pktio_open(odp_pktio_t id ODP_UNUSED, if (strncmp(dev, "ipc", 3)) return -1; - odp_atomic_init_u32(&pktio_entry->s.ipc.ready, 0); + odp_atomic_init_u32(&pktio_entry->ops_data(ipc).ready, 0); /* Shared info about remote pktio */ if (sscanf(dev, "ipc:%d:%s", &pid, tail) == 2) { - pktio_entry->s.ipc.type = PKTIO_TYPE_IPC_SLAVE; + pktio_entry->ops_data(ipc).type = PKTIO_TYPE_IPC_SLAVE; snprintf(name, sizeof(name), "ipc:%s_info", tail); IPC_ODP_DBG("lookup for name %s for pid %d\n", name, pid); @@ -359,12 +358,12 @@ static int ipc_pktio_open(odp_pktio_t id ODP_UNUSED, odp_shm_free(shm); return -1; } - pktio_entry->s.ipc.pinfo = pinfo; - pktio_entry->s.ipc.pinfo_shm = shm; + pktio_entry->ops_data(ipc).pinfo = pinfo; + pktio_entry->ops_data(ipc).pinfo_shm = shm; ODP_DBG("process %d is slave\n", getpid()); ret = _ipc_init_slave(name, pktio_entry, pool); } else { - pktio_entry->s.ipc.type = PKTIO_TYPE_IPC_MASTER; + pktio_entry->ops_data(ipc).type = PKTIO_TYPE_IPC_MASTER; snprintf(name, sizeof(name), "%s_info", dev); shm = odp_shm_reserve(name, sizeof(struct pktio_info), ODP_CACHE_LINE_SIZE, @@ -377,8 +376,8 @@ static int ipc_pktio_open(odp_pktio_t id ODP_UNUSED, pinfo = odp_shm_addr(shm); pinfo->master.init_done = 0; pinfo->master.pool_name[0] = 0; - pktio_entry->s.ipc.pinfo = pinfo; - pktio_entry->s.ipc.pinfo_shm = shm; + pktio_entry->ops_data(ipc).pinfo = pinfo; + pktio_entry->ops_data(ipc).pinfo_shm = shm; ODP_DBG("process %d is master\n", getpid()); ret = _ipc_init_master(pktio_entry, dev, pool); } @@ -406,7 +405,7 @@ static void _ipc_free_ring_packets(pktio_entry_t *pktio_entry, _ring_t *r) for (i = 0; i < ret; i++) { odp_packet_hdr_t *phdr; odp_packet_t pkt; - void *mbase = pktio_entry->s.ipc.pool_mdata_base; + void *mbase = pktio_entry->ops_data(ipc).pool_mdata_base; phdr = (void *)((uint8_t *)mbase + offsets[i]); pkt = packet_handle(phdr); @@ -427,15 +426,15 @@ static int ipc_pktio_recv_lockless(pktio_entry_t *pktio_entry, uint32_t ready; int pkts_ring; - ready = odp_atomic_load_u32(&pktio_entry->s.ipc.ready); + ready = odp_atomic_load_u32(&pktio_entry->ops_data(ipc).ready); if (odp_unlikely(!ready)) { IPC_ODP_DBG("start pktio is missing before usage?\n"); return 0; } - _ipc_free_ring_packets(pktio_entry, pktio_entry->s.ipc.tx.free); + _ipc_free_ring_packets(pktio_entry, pktio_entry->ops_data(ipc).tx.free); - r = pktio_entry->s.ipc.rx.recv; + r = pktio_entry->ops_data(ipc).rx.recv; pkts = _ring_mc_dequeue_burst(r, ipcbufs_p, len); if (odp_unlikely(pkts < 0)) ODP_ABORT("internal error dequeue\n"); @@ -452,10 +451,10 @@ static int ipc_pktio_recv_lockless(pktio_entry_t *pktio_entry, uint64_t data_pool_off; void *rmt_data_ptr; - phdr = (void *)((uint8_t *)pktio_entry->s.ipc.pool_mdata_base + + phdr = (void *)((uint8_t *)pktio_entry->ops_data(ipc).pool_mdata_base + offsets[i]); - pool = pktio_entry->s.ipc.pool; + pool = pktio_entry->ops_data(ipc).pool; if (odp_unlikely(pool == ODP_POOL_INVALID)) ODP_ABORT("invalid pool"); @@ -478,10 +477,10 @@ static int ipc_pktio_recv_lockless(pktio_entry_t *pktio_entry, if (odp_unlikely(!pkt_data)) ODP_ABORT("unable to map pkt_data ipc_slave %d\n", (PKTIO_TYPE_IPC_SLAVE == - pktio_entry->s.ipc.type)); + pktio_entry->ops_data(ipc).type)); /* Copy packet data from shared pool to local pool. */ - rmt_data_ptr = (uint8_t *)pktio_entry->s.ipc.pool_mdata_base + + rmt_data_ptr = (uint8_t *)pktio_entry->ops_data(ipc).pool_mdata_base + data_pool_off; memcpy(pkt_data, rmt_data_ptr, phdr->frame_len); @@ -499,7 +498,7 @@ static int ipc_pktio_recv_lockless(pktio_entry_t *pktio_entry, } /* Now tell other process that we no longer need that buffers.*/ - r_p = pktio_entry->s.ipc.rx.free; + r_p = pktio_entry->ops_data(ipc).rx.free; repeat: pkts_ring = _ring_mp_enqueue_burst(r_p, ipcbufs_p, pkts); @@ -539,7 +538,7 @@ static int ipc_pktio_send_lockless(pktio_entry_t *pktio_entry, void **rbuf_p; int ret; int i; - uint32_t ready = odp_atomic_load_u32(&pktio_entry->s.ipc.ready); + uint32_t ready = odp_atomic_load_u32(&pktio_entry->ops_data(ipc).ready); odp_packet_t pkt_table_mapped[len]; /**< Ready to send packet has to be * in memory mapped pool. */ uintptr_t offsets[len]; @@ -547,12 +546,12 @@ static int ipc_pktio_send_lockless(pktio_entry_t *pktio_entry, if (odp_unlikely(!ready)) return 0; - _ipc_free_ring_packets(pktio_entry, pktio_entry->s.ipc.tx.free); + _ipc_free_ring_packets(pktio_entry, pktio_entry->ops_data(ipc).tx.free); /* Copy packets to shm shared pool if they are in different */ for (i = 0; i < len; i++) { odp_packet_t pkt = pkt_table[i]; - pool_t *ipc_pool = pool_entry_from_hdl(pktio_entry->s.ipc.pool); + pool_t *ipc_pool = pool_entry_from_hdl(pktio_entry->ops_data(ipc).pool); odp_buffer_bits_t handle; uint32_t pkt_pool_id; @@ -561,7 +560,7 @@ static int ipc_pktio_send_lockless(pktio_entry_t *pktio_entry, if (pkt_pool_id != ipc_pool->pool_idx) { odp_packet_t newpkt; - newpkt = odp_packet_copy(pkt, pktio_entry->s.ipc.pool); + newpkt = odp_packet_copy(pkt, pktio_entry->ops_data(ipc).pool); if (newpkt == ODP_PACKET_INVALID) ODP_ABORT("Unable to copy packet\n"); @@ -596,12 +595,12 @@ static int ipc_pktio_send_lockless(pktio_entry_t *pktio_entry, /* Put packets to ring to be processed by other process. */ rbuf_p = (void *)&offsets[0]; - r = pktio_entry->s.ipc.tx.send; + r = pktio_entry->ops_data(ipc).tx.send; ret = _ring_mp_enqueue_burst(r, rbuf_p, len); if (odp_unlikely(ret < 0)) { ODP_ERR("pid %d odp_ring_mp_enqueue_bulk fail, ipc_slave %d, ret %d\n", getpid(), - (PKTIO_TYPE_IPC_SLAVE == pktio_entry->s.ipc.type), + (PKTIO_TYPE_IPC_SLAVE == pktio_entry->ops_data(ipc).type), ret); ODP_ERR("odp_ring_full: %d, odp_ring_count %d, _ring_free_count %d\n", _ring_full(r), _ring_count(r), @@ -641,14 +640,14 @@ static int ipc_mac_addr_get(pktio_entry_t *pktio_entry ODP_UNUSED, static int ipc_start(pktio_entry_t *pktio_entry) { - uint32_t ready = odp_atomic_load_u32(&pktio_entry->s.ipc.ready); + uint32_t ready = odp_atomic_load_u32(&pktio_entry->ops_data(ipc).ready); if (ready) { ODP_ABORT("%s Already started\n", pktio_entry->s.name); return -1; } - if (pktio_entry->s.ipc.type == PKTIO_TYPE_IPC_MASTER) + if (pktio_entry->ops_data(ipc).type == PKTIO_TYPE_IPC_MASTER) return _ipc_master_start(pktio_entry); else return _ipc_slave_start(pktio_entry); @@ -658,20 +657,20 @@ static int ipc_stop(pktio_entry_t *pktio_entry) { unsigned tx_send = 0, tx_free = 0; - odp_atomic_store_u32(&pktio_entry->s.ipc.ready, 0); + odp_atomic_store_u32(&pktio_entry->ops_data(ipc).ready, 0); - if (pktio_entry->s.ipc.tx.send) - _ipc_free_ring_packets(pktio_entry, pktio_entry->s.ipc.tx.send); + if (pktio_entry->ops_data(ipc).tx.send) + _ipc_free_ring_packets(pktio_entry, pktio_entry->ops_data(ipc).tx.send); /* other process can transfer packets from one ring to * other, use delay here to free that packets. */ sleep(1); - if (pktio_entry->s.ipc.tx.free) - _ipc_free_ring_packets(pktio_entry, pktio_entry->s.ipc.tx.free); + if (pktio_entry->ops_data(ipc).tx.free) + _ipc_free_ring_packets(pktio_entry, pktio_entry->ops_data(ipc).tx.free); - if (pktio_entry->s.ipc.tx.send) - tx_send = _ring_count(pktio_entry->s.ipc.tx.send); - if (pktio_entry->s.ipc.tx.free) - tx_free = _ring_count(pktio_entry->s.ipc.tx.free); + if (pktio_entry->ops_data(ipc).tx.send) + tx_send = _ring_count(pktio_entry->ops_data(ipc).tx.send); + if (pktio_entry->ops_data(ipc).tx.free) + tx_free = _ring_count(pktio_entry->ops_data(ipc).tx.free); if (tx_send | tx_free) { ODP_DBG("IPC rings: tx send %d tx free %d\n", tx_send, tx_free); @@ -690,7 +689,7 @@ static int ipc_close(pktio_entry_t *pktio_entry) ipc_stop(pktio_entry); - odp_shm_free(pktio_entry->s.ipc.remote_pool_shm); + odp_shm_free(pktio_entry->ops_data(ipc).remote_pool_shm); if (sscanf(dev, "ipc:%d:%s", &pid, tail) == 2) snprintf(name, sizeof(name), "ipc:%s", tail); @@ -698,7 +697,7 @@ static int ipc_close(pktio_entry_t *pktio_entry) snprintf(name, sizeof(name), "%s", dev); /* unlink this pktio info for both master and slave */ - odp_shm_free(pktio_entry->s.ipc.pinfo_shm); + odp_shm_free(pktio_entry->ops_data(ipc).pinfo_shm); /* destroy rings */ snprintf(ipc_shm_name, sizeof(ipc_shm_name), "%s_s_cons", name); @@ -720,23 +719,37 @@ static int ipc_pktio_init_global(void) return 0; } -const pktio_if_ops_t ipc_pktio_ops = { +pktio_ops_module_t ipc_pktio_ops = { .name = "ipc", - .print = NULL, - .init_global = ipc_pktio_init_global, .init_local = NULL, - .term = NULL, + .term_local = NULL, + .init_global = ipc_pktio_init_global, + .term_global = NULL, .open = ipc_pktio_open, .close = ipc_close, - .recv = ipc_pktio_recv, - .send = ipc_pktio_send, .start = ipc_start, .stop = ipc_stop, + .stats = NULL, + .stats_reset = NULL, + .pktin_ts_res = NULL, + .pktin_ts_from_ns = NULL, + .recv = ipc_pktio_recv, + .send = ipc_pktio_send, .mtu_get = ipc_mtu_get, .promisc_mode_set = NULL, .promisc_mode_get = NULL, .mac_get = ipc_mac_addr_get, - .pktin_ts_res = NULL, - .pktin_ts_from_ns = NULL, - .config = NULL + .link_status = NULL, + .capability = NULL, + .config = NULL, + .input_queues_config = NULL, + .output_queues_config = NULL, + .print = NULL, }; + +MODULE_CONSTRUCTOR(ipc_pktio_ops) +{ + INIT_LIST_HEAD(&ipc_pktio_ops.list); + + subsystem_register_module(pktio_ops, &ipc_pktio_ops); +} diff --git a/platform/linux-generic/pktio/loop.c b/platform/linux-generic/pktio/loop.c index c825393a..56567ea5 100644 --- a/platform/linux-generic/pktio/loop.c +++ b/platform/linux-generic/pktio/loop.c @@ -35,10 +35,10 @@ static int loopback_open(odp_pktio_t id, pktio_entry_t *pktio_entry, snprintf(loopq_name, sizeof(loopq_name), "%" PRIu64 "-pktio_loopq", odp_pktio_to_u64(id)); - pktio_entry->s.pkt_loop.loopq = + pktio_entry->ops_data(loopback).loopq = odp_queue_create(loopq_name, NULL); - if (pktio_entry->s.pkt_loop.loopq == ODP_QUEUE_INVALID) + if (pktio_entry->ops_data(loopback).loopq == ODP_QUEUE_INVALID) return -1; loopback_stats_reset(pktio_entry); @@ -48,7 +48,7 @@ static int loopback_open(odp_pktio_t id, pktio_entry_t *pktio_entry, static int loopback_close(pktio_entry_t *pktio_entry) { - return odp_queue_destroy(pktio_entry->s.pkt_loop.loopq); + return odp_queue_destroy(pktio_entry->ops_data(loopback).loopq); } static int loopback_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, @@ -70,7 +70,7 @@ static int loopback_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, odp_ticketlock_lock(&pktio_entry->s.rxl); - queue = queue_fn->from_ext(pktio_entry->s.pkt_loop.loopq); + queue = queue_fn->from_ext(pktio_entry->ops_data(loopback).loopq); nbr = queue_fn->deq_multi(queue, hdr_tbl, len); if (pktio_entry->s.config.pktin.bit.ts_all || @@ -170,7 +170,7 @@ static int loopback_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED, odp_ticketlock_lock(&pktio_entry->s.txl); - queue = queue_fn->from_ext(pktio_entry->s.pkt_loop.loopq); + queue = queue_fn->from_ext(pktio_entry->ops_data(loopback).loopq); ret = queue_fn->enq_multi(queue, hdr_tbl, len); if (ret > 0) { @@ -223,13 +223,13 @@ static int loopback_capability(pktio_entry_t *pktio_entry ODP_UNUSED, static int loopback_promisc_mode_set(pktio_entry_t *pktio_entry, odp_bool_t enable) { - pktio_entry->s.pkt_loop.promisc = enable; + pktio_entry->ops_data(loopback).promisc = enable; return 0; } static int loopback_promisc_mode_get(pktio_entry_t *pktio_entry) { - return pktio_entry->s.pkt_loop.promisc ? 1 : 0; + return pktio_entry->ops_data(loopback).promisc ? 1 : 0; } static int loopback_stats(pktio_entry_t *pktio_entry, @@ -251,18 +251,20 @@ static int loop_init_global(void) return 0; } -const pktio_if_ops_t loopback_pktio_ops = { - .name = "loop", - .print = NULL, - .init_global = loop_init_global, +pktio_ops_module_t loopback_pktio_ops = { + .name = "loopback", .init_local = NULL, - .term = NULL, + .term_local = NULL, + .init_global = loop_init_global, + .term_global = NULL, .open = loopback_open, .close = loopback_close, .start = NULL, .stop = NULL, .stats = loopback_stats, .stats_reset = loopback_stats_reset, + .pktin_ts_res = NULL, + .pktin_ts_from_ns = NULL, .recv = loopback_recv, .send = loopback_send, .mtu_get = loopback_mtu_get, @@ -271,9 +273,15 @@ const pktio_if_ops_t loopback_pktio_ops = { .mac_get = loopback_mac_addr_get, .link_status = loopback_link_status, .capability = loopback_capability, - .pktin_ts_res = NULL, - .pktin_ts_from_ns = NULL, .config = NULL, .input_queues_config = NULL, .output_queues_config = NULL, + .print = NULL, }; + +MODULE_CONSTRUCTOR(loopback_pktio_ops) +{ + INIT_LIST_HEAD(&loopback_pktio_ops.list); + + subsystem_register_module(pktio_ops, &loopback_pktio_ops); +} diff --git a/platform/linux-generic/pktio/ops_subsystem.c b/platform/linux-generic/pktio/ops_subsystem.c new file mode 100644 index 00000000..de2fc3e5 --- /dev/null +++ b/platform/linux-generic/pktio/ops_subsystem.c @@ -0,0 +1,19 @@ +/* Copyright (c) 2017, ARM Limited. All rights reserved. + * + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#define SUBSYSTEM_VERSION 0x00010000UL +SUBSYSTEM(pktio_ops, "packet IO operations", SUBSYSTEM_VERSION); + +SUBSYSTEM_CONSTRUCTOR(pktio_ops) +{ + subsystem_constructor(pktio_ops); + + /* Further initialization per subsystem */ +} diff --git a/platform/linux-generic/pktio/pcap.c b/platform/linux-generic/pktio/pcap.c index a467b640..7743938b 100644 --- a/platform/linux-generic/pktio/pcap.c +++ b/platform/linux-generic/pktio/pcap.c @@ -51,7 +51,7 @@ static const char pcap_mac[] = {0x02, 0xe9, 0x34, 0x80, 0x73, 0x04}; static int pcapif_stats_reset(pktio_entry_t *pktio_entry); -static int _pcapif_parse_devname(pkt_pcap_t *pcap, const char *devname) +static int _pcapif_parse_devname(pktio_ops_pcap_data_t *pcap, const char *devname) { char *tok; char in[PKTIO_NAME_LEN]; @@ -80,7 +80,7 @@ static int _pcapif_parse_devname(pkt_pcap_t *pcap, const char *devname) return 0; } -static int _pcapif_init_rx(pkt_pcap_t *pcap) +static int _pcapif_init_rx(pktio_ops_pcap_data_t *pcap) { char errbuf[PCAP_ERRBUF_SIZE]; int linktype; @@ -101,7 +101,7 @@ static int _pcapif_init_rx(pkt_pcap_t *pcap) return 0; } -static int _pcapif_init_tx(pkt_pcap_t *pcap) +static int _pcapif_init_tx(pktio_ops_pcap_data_t *pcap) { pcap_t *tx = pcap->rx; @@ -136,10 +136,10 @@ static int _pcapif_init_tx(pkt_pcap_t *pcap) static int pcapif_init(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry, const char *devname, odp_pool_t pool) { - pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap; + pktio_ops_pcap_data_t *pcap = &pktio_entry->ops_data(pcap); int ret; - memset(pcap, 0, sizeof(pkt_pcap_t)); + memset(pcap, 0, sizeof(pktio_ops_pcap_data_t)); pcap->loop_cnt = 1; pcap->loops = 1; pcap->pool = pool; @@ -163,7 +163,7 @@ static int pcapif_init(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry, static int pcapif_close(pktio_entry_t *pktio_entry) { - pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap; + pktio_ops_pcap_data_t *pcap = &pktio_entry->ops_data(pcap); if (pcap->tx_dump) pcap_dump_close(pcap->tx_dump); @@ -181,7 +181,7 @@ static int pcapif_close(pktio_entry_t *pktio_entry) return 0; } -static int _pcapif_reopen(pkt_pcap_t *pcap) +static int _pcapif_reopen(pktio_ops_pcap_data_t *pcap) { char errbuf[PCAP_ERRBUF_SIZE]; @@ -210,7 +210,7 @@ static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, int index ODP_UNUSED, odp_packet_t pkt; odp_packet_hdr_t *pkt_hdr; uint32_t pkt_len; - pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap; + pktio_ops_pcap_data_t *pcap = &pktio_entry->ops_data(pcap); odp_time_t ts_val; odp_time_t *ts = NULL; @@ -270,7 +270,7 @@ static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, int index ODP_UNUSED, return i; } -static int _pcapif_dump_pkt(pkt_pcap_t *pcap, odp_packet_t pkt) +static int _pcapif_dump_pkt(pktio_ops_pcap_data_t *pcap, odp_packet_t pkt) { struct pcap_pkthdr hdr; @@ -293,7 +293,7 @@ static int _pcapif_dump_pkt(pkt_pcap_t *pcap, odp_packet_t pkt) static int pcapif_send_pkt(pktio_entry_t *pktio_entry, int index ODP_UNUSED, const odp_packet_t pkts[], int len) { - pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap; + pktio_ops_pcap_data_t *pcap = &pktio_entry->ops_data(pcap); int i; odp_ticketlock_lock(&pktio_entry->s.txl); @@ -361,7 +361,7 @@ static int pcapif_promisc_mode_set(pktio_entry_t *pktio_entry, { char filter_exp[64] = {0}; struct bpf_program bpf; - pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap; + pktio_ops_pcap_data_t *pcap = &pktio_entry->ops_data(pcap); if (!pcap->rx) { pcap->promisc = enable; @@ -401,7 +401,7 @@ static int pcapif_promisc_mode_set(pktio_entry_t *pktio_entry, static int pcapif_promisc_mode_get(pktio_entry_t *pktio_entry) { - return pktio_entry->s.pkt_pcap.promisc; + return pktio_entry->ops_data(pcap).promisc; } static int pcapif_stats_reset(pktio_entry_t *pktio_entry) @@ -423,25 +423,37 @@ static int pcapif_init_global(void) return 0; } -const pktio_if_ops_t pcap_pktio_ops = { +pktio_ops_module_t pcap_pktio_ops = { .name = "pcap", - .print = NULL, - .init_global = pcapif_init_global, .init_local = NULL, + .term_local = NULL, + .init_global = pcapif_init_global, + .term_global = NULL, .open = pcapif_init, .close = pcapif_close, + .start = NULL, + .stop = NULL, .stats = pcapif_stats, .stats_reset = pcapif_stats_reset, + .pktin_ts_res = NULL, + .pktin_ts_from_ns = NULL, .recv = pcapif_recv_pkt, .send = pcapif_send_pkt, .mtu_get = pcapif_mtu_get, .promisc_mode_set = pcapif_promisc_mode_set, .promisc_mode_get = pcapif_promisc_mode_get, .mac_get = pcapif_mac_addr_get, + .link_status = NULL, .capability = pcapif_capability, - .pktin_ts_res = NULL, - .pktin_ts_from_ns = NULL, .config = NULL, .input_queues_config = NULL, .output_queues_config = NULL, + .print = NULL, }; + +MODULE_CONSTRUCTOR(pcap_pktio_ops) +{ + INIT_LIST_HEAD(&pcap_pktio_ops.list); + + subsystem_register_module(pktio_ops, &pcap_pktio_ops); +} diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c index a383adc6..91c17812 100644 --- a/platform/linux-generic/pktio/socket.c +++ b/platform/linux-generic/pktio/socket.c @@ -33,7 +33,6 @@ #include #include -#include #include #include #include @@ -455,8 +454,8 @@ void rss_conf_print(const odp_pktin_hash_proto_t *hash_proto) */ static int sock_close(pktio_entry_t *pktio_entry) { - pkt_sock_t *pkt_sock = &pktio_entry->s.pkt_sock; - if (pkt_sock->sockfd != -1 && close(pkt_sock->sockfd) != 0) { + pktio_ops_socket_data_t *opdata = &pktio_entry->ops_data(_socket); + if (opdata->sockfd != -1 && close(opdata->sockfd) != 0) { __odp_errno = errno; ODP_ERR("close(sockfd): %s\n", strerror(errno)); return -1; @@ -477,17 +476,17 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev, struct ifreq ethreq; struct sockaddr_ll sa_ll; char shm_name[ODP_SHM_NAME_LEN]; - pkt_sock_t *pkt_sock = &pktio_entry->s.pkt_sock; + pktio_ops_socket_data_t *opdata = &pktio_entry->ops_data(_socket); odp_pktio_stats_t cur_stats; /* Init pktio entry */ - memset(pkt_sock, 0, sizeof(*pkt_sock)); + memset(opdata, 0, sizeof(*opdata)); /* set sockfd to -1, because a valid socked might be initialized to 0 */ - pkt_sock->sockfd = -1; + opdata->sockfd = -1; if (pool == ODP_POOL_INVALID) return -1; - pkt_sock->pool = pool; + opdata->pool = pool; snprintf(shm_name, ODP_SHM_NAME_LEN, "%s-%s", "pktio", netdev); shm_name[ODP_SHM_NAME_LEN - 1] = '\0'; @@ -497,7 +496,7 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev, ODP_ERR("socket(): %s\n", strerror(errno)); goto error; } - pkt_sock->sockfd = sockfd; + opdata->sockfd = sockfd; /* get if index */ memset(ðreq, 0, sizeof(struct ifreq)); @@ -511,12 +510,12 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev, } if_idx = ethreq.ifr_ifindex; - err = mac_addr_get_fd(sockfd, netdev, pkt_sock->if_mac); + err = mac_addr_get_fd(sockfd, netdev, opdata->if_mac); if (err != 0) goto error; - pkt_sock->mtu = mtu_get_fd(sockfd, netdev); - if (!pkt_sock->mtu) + opdata->mtu = mtu_get_fd(sockfd, netdev); + if (!opdata->mtu) goto error; /* bind socket to if */ @@ -530,7 +529,7 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev, goto error; } - err = ethtool_stats_get_fd(pktio_entry->s.pkt_sock.sockfd, + err = ethtool_stats_get_fd(pktio_entry->ops_data(_socket).sockfd, pktio_entry->s.name, &cur_stats); if (err != 0) { @@ -601,11 +600,11 @@ static uint32_t _rx_pkt_to_iovec(odp_packet_t pkt, static int sock_mmsg_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, odp_packet_t pkt_table[], int len) { - pkt_sock_t *pkt_sock = &pktio_entry->s.pkt_sock; - odp_pool_t pool = pkt_sock->pool; + pktio_ops_socket_data_t *opdata = &pktio_entry->ops_data(_socket); + odp_pool_t pool = opdata->pool; odp_time_t ts_val; odp_time_t *ts = NULL; - const int sockfd = pkt_sock->sockfd; + const int sockfd = opdata->sockfd; struct mmsghdr msgvec[len]; struct iovec iovecs[len][MAX_SEGS]; int nb_rx = 0; @@ -621,7 +620,7 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, memset(msgvec, 0, sizeof(msgvec)); - nb_pkts = packet_alloc_multi(pool, pkt_sock->mtu, pkt_table, len); + nb_pkts = packet_alloc_multi(pool, opdata->mtu, pkt_table, len); for (i = 0; i < nb_pkts; i++) { msgvec[i].msg_hdr.msg_iovlen = _rx_pkt_to_iovec(pkt_table[i], iovecs[i]); @@ -656,7 +655,7 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, } /* Don't receive packets sent by ourselves */ - if (odp_unlikely(ethaddrs_equal(pkt_sock->if_mac, + if (odp_unlikely(ethaddrs_equal(opdata->if_mac, eth_hdr->h_source))) { odp_packet_free(pkt); continue; @@ -716,7 +715,7 @@ static uint32_t _tx_pkt_to_iovec(odp_packet_t pkt, static int sock_mmsg_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED, const odp_packet_t pkt_table[], int len) { - pkt_sock_t *pkt_sock = &pktio_entry->s.pkt_sock; + pktio_ops_socket_data_t *opdata = &pktio_entry->ops_data(_socket); struct mmsghdr msgvec[len]; struct iovec iovecs[len][MAX_SEGS]; int ret; @@ -725,7 +724,7 @@ static int sock_mmsg_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED, odp_ticketlock_lock(&pktio_entry->s.txl); - sockfd = pkt_sock->sockfd; + sockfd = opdata->sockfd; memset(msgvec, 0, sizeof(msgvec)); for (i = 0; i < len; i++) { @@ -762,7 +761,7 @@ static int sock_mmsg_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED, */ static uint32_t sock_mtu_get(pktio_entry_t *pktio_entry) { - return pktio_entry->s.pkt_sock.mtu; + return pktio_entry->ops_data(_socket).mtu; } /* @@ -771,7 +770,7 @@ static uint32_t sock_mtu_get(pktio_entry_t *pktio_entry) static int sock_mac_addr_get(pktio_entry_t *pktio_entry, void *mac_addr) { - memcpy(mac_addr, pktio_entry->s.pkt_sock.if_mac, ETH_ALEN); + memcpy(mac_addr, pktio_entry->ops_data(_socket).if_mac, ETH_ALEN); return ETH_ALEN; } @@ -781,7 +780,7 @@ static int sock_mac_addr_get(pktio_entry_t *pktio_entry, static int sock_promisc_mode_set(pktio_entry_t *pktio_entry, odp_bool_t enable) { - return promisc_mode_set_fd(pktio_entry->s.pkt_sock.sockfd, + return promisc_mode_set_fd(pktio_entry->ops_data(_socket).sockfd, pktio_entry->s.name, enable); } @@ -790,13 +789,13 @@ static int sock_promisc_mode_set(pktio_entry_t *pktio_entry, */ static int sock_promisc_mode_get(pktio_entry_t *pktio_entry) { - return promisc_mode_get_fd(pktio_entry->s.pkt_sock.sockfd, + return promisc_mode_get_fd(pktio_entry->ops_data(_socket).sockfd, pktio_entry->s.name); } static int sock_link_status(pktio_entry_t *pktio_entry) { - return link_status_fd(pktio_entry->s.pkt_sock.sockfd, + return link_status_fd(pktio_entry->ops_data(_socket).sockfd, pktio_entry->s.name); } @@ -825,7 +824,7 @@ static int sock_stats(pktio_entry_t *pktio_entry, return sock_stats_fd(pktio_entry, stats, - pktio_entry->s.pkt_sock.sockfd); + pktio_entry->ops_data(_socket).sockfd); } static int sock_stats_reset(pktio_entry_t *pktio_entry) @@ -837,7 +836,7 @@ static int sock_stats_reset(pktio_entry_t *pktio_entry) } return sock_stats_reset_fd(pktio_entry, - pktio_entry->s.pkt_sock.sockfd); + pktio_entry->ops_data(_socket).sockfd); } static int sock_init_global(void) @@ -853,18 +852,20 @@ static int sock_init_global(void) return 0; } -const pktio_if_ops_t sock_mmsg_pktio_ops = { +pktio_ops_module_t socket_pktio_ops = { .name = "socket", - .print = NULL, - .init_global = sock_init_global, .init_local = NULL, - .term = NULL, + .term_local = NULL, + .init_global = sock_init_global, + .term_global = NULL, .open = sock_mmsg_open, .close = sock_close, .start = NULL, .stop = NULL, .stats = sock_stats, .stats_reset = sock_stats_reset, + .pktin_ts_res = NULL, + .pktin_ts_from_ns = NULL, .recv = sock_mmsg_recv, .send = sock_mmsg_send, .mtu_get = sock_mtu_get, @@ -873,9 +874,15 @@ const pktio_if_ops_t sock_mmsg_pktio_ops = { .mac_get = sock_mac_addr_get, .link_status = sock_link_status, .capability = sock_capability, - .pktin_ts_res = NULL, - .pktin_ts_from_ns = NULL, .config = NULL, .input_queues_config = NULL, .output_queues_config = NULL, + .print = NULL, }; + +MODULE_CONSTRUCTOR(socket_pktio_ops) +{ + INIT_LIST_HEAD(&socket_pktio_ops.list); + + subsystem_register_module(pktio_ops, &socket_pktio_ops); +} diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c index 2dba7b08..da53e697 100644 --- a/platform/linux-generic/pktio/socket_mmap.c +++ b/platform/linux-generic/pktio/socket_mmap.c @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -37,10 +36,10 @@ static int disable_pktio; /** !0 this pktio disabled, 0 enabled */ -static int set_pkt_sock_fanout_mmap(pkt_sock_mmap_t *const pkt_sock, - int sock_group_idx) +static int set_fanout_mmap(pktio_ops_socket_mmap_data_t *const opdata, + int sock_group_idx) { - int sockfd = pkt_sock->sockfd; + int sockfd = opdata->sockfd; int val; int err; uint16_t fanout_group; @@ -144,7 +143,7 @@ static uint8_t *pkt_mmap_vlan_insert(uint8_t *l2_hdr_ptr, } static inline unsigned pkt_mmap_v2_rx(pktio_entry_t *pktio_entry, - pkt_sock_mmap_t *pkt_sock, + pktio_ops_socket_mmap_data_t *opdata, odp_packet_t pkt_table[], unsigned len, unsigned char if_mac[]) { @@ -164,13 +163,13 @@ static inline unsigned pkt_mmap_v2_rx(pktio_entry_t *pktio_entry, pktio_entry->s.config.pktin.bit.ts_ptp) ts = &ts_val; - ring = &pkt_sock->rx_ring; + ring = &opdata->rx_ring; frame_num = ring->frame_num; for (i = 0, nb_rx = 0; i < len; i++) { odp_packet_hdr_t *hdr; odp_packet_hdr_t parsed_hdr; - odp_pool_t pool = pkt_sock->pool; + odp_pool_t pool = opdata->pool; int num; if (!mmap_rx_kernel_ready(ring->rd[frame_num].iov_base)) @@ -411,70 +410,71 @@ static int mmap_setup_ring(int sock, struct ring *ring, int type, return 0; } -static int mmap_sock(pkt_sock_mmap_t *pkt_sock) +static int mmap_sock(pktio_ops_socket_mmap_data_t *opdata) { int i; - int sock = pkt_sock->sockfd; + int sock = opdata->sockfd; /* map rx + tx buffer to userspace : they are in this order */ - pkt_sock->mmap_len = - pkt_sock->rx_ring.req.tp_block_size * - pkt_sock->rx_ring.req.tp_block_nr + - pkt_sock->tx_ring.req.tp_block_size * - pkt_sock->tx_ring.req.tp_block_nr; - - pkt_sock->mmap_base = - mmap(NULL, pkt_sock->mmap_len, PROT_READ | PROT_WRITE, + opdata->mmap_len = + opdata->rx_ring.req.tp_block_size * + opdata->rx_ring.req.tp_block_nr + + opdata->tx_ring.req.tp_block_size * + opdata->tx_ring.req.tp_block_nr; + + opdata->mmap_base = + mmap(NULL, opdata->mmap_len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED | MAP_POPULATE, sock, 0); - if (pkt_sock->mmap_base == MAP_FAILED) { + if (opdata->mmap_base == MAP_FAILED) { __odp_errno = errno; ODP_ERR("mmap rx&tx buffer failed: %s\n", strerror(errno)); return -1; } - pkt_sock->rx_ring.mm_space = pkt_sock->mmap_base; - memset(pkt_sock->rx_ring.rd, 0, pkt_sock->rx_ring.rd_len); - for (i = 0; i < pkt_sock->rx_ring.rd_num; ++i) { - pkt_sock->rx_ring.rd[i].iov_base = - pkt_sock->rx_ring.mm_space - + (i * pkt_sock->rx_ring.flen); - pkt_sock->rx_ring.rd[i].iov_len = pkt_sock->rx_ring.flen; + opdata->rx_ring.mm_space = opdata->mmap_base; + memset(opdata->rx_ring.rd, 0, opdata->rx_ring.rd_len); + for (i = 0; i < opdata->rx_ring.rd_num; ++i) { + opdata->rx_ring.rd[i].iov_base = + opdata->rx_ring.mm_space + + (i * opdata->rx_ring.flen); + opdata->rx_ring.rd[i].iov_len = opdata->rx_ring.flen; } - pkt_sock->tx_ring.mm_space = - pkt_sock->mmap_base + pkt_sock->rx_ring.mm_len; - memset(pkt_sock->tx_ring.rd, 0, pkt_sock->tx_ring.rd_len); - for (i = 0; i < pkt_sock->tx_ring.rd_num; ++i) { - pkt_sock->tx_ring.rd[i].iov_base = - pkt_sock->tx_ring.mm_space - + (i * pkt_sock->tx_ring.flen); - pkt_sock->tx_ring.rd[i].iov_len = pkt_sock->tx_ring.flen; + opdata->tx_ring.mm_space = + opdata->mmap_base + opdata->rx_ring.mm_len; + memset(opdata->tx_ring.rd, 0, opdata->tx_ring.rd_len); + for (i = 0; i < opdata->tx_ring.rd_num; ++i) { + opdata->tx_ring.rd[i].iov_base = + opdata->tx_ring.mm_space + + (i * opdata->tx_ring.flen); + opdata->tx_ring.rd[i].iov_len = opdata->tx_ring.flen; } return 0; } -static int mmap_unmap_sock(pkt_sock_mmap_t *pkt_sock) +static int mmap_unmap_sock(pktio_ops_socket_mmap_data_t *opdata) { - free(pkt_sock->rx_ring.rd); - free(pkt_sock->tx_ring.rd); - return munmap(pkt_sock->mmap_base, pkt_sock->mmap_len); + free(opdata->rx_ring.rd); + free(opdata->tx_ring.rd); + return munmap(opdata->mmap_base, opdata->mmap_len); } -static int mmap_bind_sock(pkt_sock_mmap_t *pkt_sock, const char *netdev) +static int mmap_bind_sock(pktio_ops_socket_mmap_data_t *opdata, + const char *netdev) { int ret; - pkt_sock->ll.sll_family = PF_PACKET; - pkt_sock->ll.sll_protocol = htons(ETH_P_ALL); - pkt_sock->ll.sll_ifindex = if_nametoindex(netdev); - pkt_sock->ll.sll_hatype = 0; - pkt_sock->ll.sll_pkttype = 0; - pkt_sock->ll.sll_halen = 0; + opdata->ll.sll_family = PF_PACKET; + opdata->ll.sll_protocol = htons(ETH_P_ALL); + opdata->ll.sll_ifindex = if_nametoindex(netdev); + opdata->ll.sll_hatype = 0; + opdata->ll.sll_pkttype = 0; + opdata->ll.sll_halen = 0; - ret = bind(pkt_sock->sockfd, (struct sockaddr *)&pkt_sock->ll, - sizeof(pkt_sock->ll)); + ret = bind(opdata->sockfd, (struct sockaddr *)&opdata->ll, + sizeof(opdata->ll)); if (ret == -1) { __odp_errno = errno; ODP_ERR("bind(to IF): %s\n", strerror(errno)); @@ -486,16 +486,17 @@ static int mmap_bind_sock(pkt_sock_mmap_t *pkt_sock, const char *netdev) static int sock_mmap_close(pktio_entry_t *entry) { - pkt_sock_mmap_t *const pkt_sock = &entry->s.pkt_sock_mmap; + pktio_ops_socket_mmap_data_t *const + opdata = &entry->ops_data(_mmap); int ret; - ret = mmap_unmap_sock(pkt_sock); + ret = mmap_unmap_sock(opdata); if (ret != 0) { ODP_ERR("mmap_unmap_sock() %s\n", strerror(errno)); return -1; } - if (pkt_sock->sockfd != -1 && close(pkt_sock->sockfd) != 0) { + if (opdata->sockfd != -1 && close(opdata->sockfd) != 0) { __odp_errno = errno; ODP_ERR("close(sockfd): %s\n", strerror(errno)); return -1; @@ -515,44 +516,45 @@ static int sock_mmap_open(odp_pktio_t id ODP_UNUSED, if (disable_pktio) return -1; - pkt_sock_mmap_t *const pkt_sock = &pktio_entry->s.pkt_sock_mmap; + pktio_ops_socket_mmap_data_t *const + opdata = &pktio_entry->ops_data(_mmap); int fanout = 1; /* Init pktio entry */ - memset(pkt_sock, 0, sizeof(*pkt_sock)); + memset(opdata, 0, sizeof(*opdata)); /* set sockfd to -1, because a valid socked might be initialized to 0 */ - pkt_sock->sockfd = -1; + opdata->sockfd = -1; if (pool == ODP_POOL_INVALID) return -1; /* Store eth buffer offset for pkt buffers from this pool */ - pkt_sock->frame_offset = 0; + opdata->frame_offset = 0; - pkt_sock->pool = pool; - pkt_sock->sockfd = mmap_pkt_socket(); - if (pkt_sock->sockfd == -1) + opdata->pool = pool; + opdata->sockfd = mmap_pkt_socket(); + if (opdata->sockfd == -1) goto error; - ret = mmap_bind_sock(pkt_sock, netdev); + ret = mmap_bind_sock(opdata, netdev); if (ret != 0) goto error; - ret = mmap_setup_ring(pkt_sock->sockfd, &pkt_sock->tx_ring, + ret = mmap_setup_ring(opdata->sockfd, &opdata->tx_ring, PACKET_TX_RING, pool, fanout); if (ret != 0) goto error; - ret = mmap_setup_ring(pkt_sock->sockfd, &pkt_sock->rx_ring, + ret = mmap_setup_ring(opdata->sockfd, &opdata->rx_ring, PACKET_RX_RING, pool, fanout); if (ret != 0) goto error; - ret = mmap_sock(pkt_sock); + ret = mmap_sock(opdata); if (ret != 0) goto error; - ret = mac_addr_get_fd(pkt_sock->sockfd, netdev, pkt_sock->if_mac); + ret = mac_addr_get_fd(opdata->sockfd, netdev, opdata->if_mac); if (ret != 0) goto error; @@ -563,14 +565,14 @@ static int sock_mmap_open(odp_pktio_t id ODP_UNUSED, goto error; } - pkt_sock->fanout = fanout; + opdata->fanout = fanout; if (fanout) { - ret = set_pkt_sock_fanout_mmap(pkt_sock, if_idx); + ret = set_fanout_mmap(opdata, if_idx); if (ret != 0) goto error; } - ret = ethtool_stats_get_fd(pktio_entry->s.pkt_sock_mmap.sockfd, + ret = ethtool_stats_get_fd(pktio_entry->ops_data(_mmap).sockfd, pktio_entry->s.name, &cur_stats); if (ret != 0) { @@ -587,7 +589,7 @@ static int sock_mmap_open(odp_pktio_t id ODP_UNUSED, } ret = sock_stats_reset_fd(pktio_entry, - pktio_entry->s.pkt_sock_mmap.sockfd); + pktio_entry->ops_data(_mmap).sockfd); if (ret != 0) goto error; @@ -601,12 +603,13 @@ static int sock_mmap_open(odp_pktio_t id ODP_UNUSED, static int sock_mmap_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, odp_packet_t pkt_table[], int len) { - pkt_sock_mmap_t *const pkt_sock = &pktio_entry->s.pkt_sock_mmap; + pktio_ops_socket_mmap_data_t *const + opdata = &pktio_entry->ops_data(_mmap); int ret; odp_ticketlock_lock(&pktio_entry->s.rxl); - ret = pkt_mmap_v2_rx(pktio_entry, pkt_sock, pkt_table, len, - pkt_sock->if_mac); + ret = pkt_mmap_v2_rx(pktio_entry, opdata, pkt_table, len, + opdata->if_mac); odp_ticketlock_unlock(&pktio_entry->s.rxl); return ret; @@ -616,10 +619,11 @@ static int sock_mmap_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED, const odp_packet_t pkt_table[], int len) { int ret; - pkt_sock_mmap_t *const pkt_sock = &pktio_entry->s.pkt_sock_mmap; + pktio_ops_socket_mmap_data_t *const + opdata = &pktio_entry->ops_data(_mmap); odp_ticketlock_lock(&pktio_entry->s.txl); - ret = pkt_mmap_v2_tx(pkt_sock->tx_ring.sock, &pkt_sock->tx_ring, + ret = pkt_mmap_v2_tx(opdata->tx_ring.sock, &opdata->tx_ring, pkt_table, len); odp_ticketlock_unlock(&pktio_entry->s.txl); @@ -628,32 +632,32 @@ static int sock_mmap_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED, static uint32_t sock_mmap_mtu_get(pktio_entry_t *pktio_entry) { - return mtu_get_fd(pktio_entry->s.pkt_sock_mmap.sockfd, + return mtu_get_fd(pktio_entry->ops_data(_mmap).sockfd, pktio_entry->s.name); } static int sock_mmap_mac_addr_get(pktio_entry_t *pktio_entry, void *mac_addr) { - memcpy(mac_addr, pktio_entry->s.pkt_sock_mmap.if_mac, ETH_ALEN); + memcpy(mac_addr, pktio_entry->ops_data(_mmap).if_mac, ETH_ALEN); return ETH_ALEN; } static int sock_mmap_promisc_mode_set(pktio_entry_t *pktio_entry, odp_bool_t enable) { - return promisc_mode_set_fd(pktio_entry->s.pkt_sock_mmap.sockfd, + return promisc_mode_set_fd(pktio_entry->ops_data(_mmap).sockfd, pktio_entry->s.name, enable); } static int sock_mmap_promisc_mode_get(pktio_entry_t *pktio_entry) { - return promisc_mode_get_fd(pktio_entry->s.pkt_sock_mmap.sockfd, + return promisc_mode_get_fd(pktio_entry->ops_data(_mmap).sockfd, pktio_entry->s.name); } static int sock_mmap_link_status(pktio_entry_t *pktio_entry) { - return link_status_fd(pktio_entry->s.pkt_sock_mmap.sockfd, + return link_status_fd(pktio_entry->ops_data(_mmap).sockfd, pktio_entry->s.name); } @@ -682,7 +686,7 @@ static int sock_mmap_stats(pktio_entry_t *pktio_entry, return sock_stats_fd(pktio_entry, stats, - pktio_entry->s.pkt_sock_mmap.sockfd); + pktio_entry->ops_data(_mmap).sockfd); } static int sock_mmap_stats_reset(pktio_entry_t *pktio_entry) @@ -694,7 +698,7 @@ static int sock_mmap_stats_reset(pktio_entry_t *pktio_entry) } return sock_stats_reset_fd(pktio_entry, - pktio_entry->s.pkt_sock_mmap.sockfd); + pktio_entry->ops_data(_mmap).sockfd); } static int sock_mmap_init_global(void) @@ -710,18 +714,20 @@ static int sock_mmap_init_global(void) return 0; } -const pktio_if_ops_t sock_mmap_pktio_ops = { - .name = "socket_mmap", - .print = NULL, - .init_global = sock_mmap_init_global, +pktio_ops_module_t socket_mmap_pktio_ops = { + .name = "socket mmap", .init_local = NULL, - .term = NULL, + .term_local = NULL, + .init_global = sock_mmap_init_global, + .term_global = NULL, .open = sock_mmap_open, .close = sock_mmap_close, .start = NULL, .stop = NULL, .stats = sock_mmap_stats, .stats_reset = sock_mmap_stats_reset, + .pktin_ts_res = NULL, + .pktin_ts_from_ns = NULL, .recv = sock_mmap_recv, .send = sock_mmap_send, .mtu_get = sock_mmap_mtu_get, @@ -730,9 +736,15 @@ const pktio_if_ops_t sock_mmap_pktio_ops = { .mac_get = sock_mmap_mac_addr_get, .link_status = sock_mmap_link_status, .capability = sock_mmap_capability, - .pktin_ts_res = NULL, - .pktin_ts_from_ns = NULL, .config = NULL, .input_queues_config = NULL, .output_queues_config = NULL, + .print = NULL, }; + +MODULE_CONSTRUCTOR(socket_mmap_pktio_ops) +{ + INIT_LIST_HEAD(&socket_mmap_pktio_ops.list); + + subsystem_register_module(pktio_ops, &socket_mmap_pktio_ops); +} diff --git a/platform/linux-generic/pktio/tap.c b/platform/linux-generic/pktio/tap.c index 650c12a7..88884f07 100644 --- a/platform/linux-generic/pktio/tap.c +++ b/platform/linux-generic/pktio/tap.c @@ -40,7 +40,6 @@ #include #include -#include #include #include #include @@ -64,15 +63,15 @@ static int tap_pktio_open(odp_pktio_t id ODP_UNUSED, int fd, skfd, flags; uint32_t mtu; struct ifreq ifr; - pkt_tap_t *tap = &pktio_entry->s.pkt_tap; + pktio_ops_tap_data_t *opdata = &pktio_entry->ops_data(tap); if (strncmp(devname, "tap:", 4) != 0) return -1; /* Init pktio entry */ - memset(tap, 0, sizeof(*tap)); - tap->fd = -1; - tap->skfd = -1; + memset(opdata, 0, sizeof(*opdata)); + opdata->fd = -1; + opdata->skfd = -1; if (pool == ODP_POOL_INVALID) return -1; @@ -114,7 +113,7 @@ static int tap_pktio_open(odp_pktio_t id ODP_UNUSED, goto tap_err; } - if (gen_random_mac(tap->if_mac) < 0) + if (gen_random_mac(opdata->if_mac) < 0) goto tap_err; /* Create AF_INET socket for network interface related operations. */ @@ -148,10 +147,10 @@ static int tap_pktio_open(odp_pktio_t id ODP_UNUSED, goto sock_err; } - tap->fd = fd; - tap->skfd = skfd; - tap->mtu = mtu; - tap->pool = pool; + opdata->fd = fd; + opdata->skfd = skfd; + opdata->mtu = mtu; + opdata->pool = pool; return 0; sock_err: close(skfd); @@ -164,15 +163,15 @@ static int tap_pktio_open(odp_pktio_t id ODP_UNUSED, static int tap_pktio_close(pktio_entry_t *pktio_entry) { int ret = 0; - pkt_tap_t *tap = &pktio_entry->s.pkt_tap; + pktio_ops_tap_data_t *opdata = &pktio_entry->ops_data(tap); - if (tap->fd != -1 && close(tap->fd) != 0) { + if (opdata->fd != -1 && close(opdata->fd) != 0) { __odp_errno = errno; ODP_ERR("close(tap->fd): %s\n", strerror(errno)); ret = -1; } - if (tap->skfd != -1 && close(tap->skfd) != 0) { + if (opdata->skfd != -1 && close(opdata->skfd) != 0) { __odp_errno = errno; ODP_ERR("close(tap->skfd): %s\n", strerror(errno)); ret = -1; @@ -191,13 +190,13 @@ static odp_packet_t pack_odp_pkt(pktio_entry_t *pktio_entry, const void *data, if (pktio_cls_enabled(pktio_entry)) { if (cls_classify_packet(pktio_entry, data, len, len, - &pktio_entry->s.pkt_tap.pool, + &pktio_entry->ops_data(tap).pool, &parsed_hdr)) { return ODP_PACKET_INVALID; } } - num = packet_alloc_multi(pktio_entry->s.pkt_tap.pool, len, &pkt, 1); + num = packet_alloc_multi(pktio_entry->ops_data(tap).pool, len, &pkt, 1); if (num != 1) return ODP_PACKET_INVALID; @@ -228,7 +227,7 @@ static int tap_pktio_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, ssize_t retval; int i; uint8_t buf[BUF_SIZE]; - pkt_tap_t *tap = &pktio_entry->s.pkt_tap; + pktio_ops_tap_data_t *opdata = &pktio_entry->ops_data(tap); odp_time_t ts_val; odp_time_t *ts = NULL; @@ -240,7 +239,7 @@ static int tap_pktio_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, for (i = 0; i < len; i++) { do { - retval = read(tap->fd, buf, BUF_SIZE); + retval = read(opdata->fd, buf, BUF_SIZE); } while (retval < 0 && errno == EINTR); if (ts != NULL) @@ -268,12 +267,12 @@ static int tap_pktio_send_lockless(pktio_entry_t *pktio_entry, int i, n; uint32_t pkt_len; uint8_t buf[BUF_SIZE]; - pkt_tap_t *tap = &pktio_entry->s.pkt_tap; + pktio_ops_tap_data_t *opdata = &pktio_entry->ops_data(tap); for (i = 0; i < len; i++) { pkt_len = odp_packet_len(pkts[i]); - if (pkt_len > tap->mtu) { + if (pkt_len > opdata->mtu) { if (i == 0) { __odp_errno = EMSGSIZE; return -1; @@ -287,7 +286,7 @@ static int tap_pktio_send_lockless(pktio_entry_t *pktio_entry, } do { - retval = write(tap->fd, buf, pkt_len); + retval = write(opdata->fd, buf, pkt_len); } while (retval < 0 && errno == EINTR); if (retval < 0) { @@ -331,10 +330,10 @@ static uint32_t tap_mtu_get(pktio_entry_t *pktio_entry) { uint32_t ret; - ret = mtu_get_fd(pktio_entry->s.pkt_tap.skfd, + ret = mtu_get_fd(pktio_entry->ops_data(tap).skfd, pktio_entry->s.name + 4); if (ret > 0) - pktio_entry->s.pkt_tap.mtu = ret; + pktio_entry->ops_data(tap).mtu = ret; return ret; } @@ -342,19 +341,19 @@ static uint32_t tap_mtu_get(pktio_entry_t *pktio_entry) static int tap_promisc_mode_set(pktio_entry_t *pktio_entry, odp_bool_t enable) { - return promisc_mode_set_fd(pktio_entry->s.pkt_tap.skfd, + return promisc_mode_set_fd(pktio_entry->ops_data(tap).skfd, pktio_entry->s.name + 4, enable); } static int tap_promisc_mode_get(pktio_entry_t *pktio_entry) { - return promisc_mode_get_fd(pktio_entry->s.pkt_tap.skfd, + return promisc_mode_get_fd(pktio_entry->ops_data(tap).skfd, pktio_entry->s.name + 4); } static int tap_mac_addr_get(pktio_entry_t *pktio_entry, void *mac_addr) { - memcpy(mac_addr, pktio_entry->s.pkt_tap.if_mac, ETH_ALEN); + memcpy(mac_addr, pktio_entry->ops_data(tap).if_mac, ETH_ALEN); return ETH_ALEN; } @@ -373,24 +372,37 @@ static int tap_capability(pktio_entry_t *pktio_entry ODP_UNUSED, return 0; } -const pktio_if_ops_t tap_pktio_ops = { +pktio_ops_module_t tap_pktio_ops = { .name = "tap", - .print = NULL, - .init_global = NULL, .init_local = NULL, - .term = NULL, + .term_local = NULL, + .init_global = NULL, + .term_global = NULL, .open = tap_pktio_open, .close = tap_pktio_close, .start = NULL, .stop = NULL, + .stats = NULL, + .stats_reset = NULL, + .pktin_ts_res = NULL, + .pktin_ts_from_ns = NULL, .recv = tap_pktio_recv, .send = tap_pktio_send, .mtu_get = tap_mtu_get, .promisc_mode_set = tap_promisc_mode_set, .promisc_mode_get = tap_promisc_mode_get, .mac_get = tap_mac_addr_get, + .link_status = NULL, .capability = tap_capability, - .pktin_ts_res = NULL, - .pktin_ts_from_ns = NULL, - .config = NULL + .config = NULL, + .input_queues_config = NULL, + .output_queues_config = NULL, + .print = NULL, }; + +MODULE_CONSTRUCTOR(tap_pktio_ops) +{ + INIT_LIST_HEAD(&tap_pktio_ops.list); + + subsystem_register_module(pktio_ops, &tap_pktio_ops); +}