1 Star 0 Fork 96

sky/gazelle_kylin_src

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0055-refactor-pkt-read-send-performance.patch 114.55 KB
一键复制 编辑 原始数据 按行查看 历史
compile_success 提交于 2023-12-04 02:54 . add select and timeout for kylin
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232
From f0e65d55ace8b4e5c1bd2023f1b62da181f421c5 Mon Sep 17 00:00:00 2001
From: jiangheng14 <jiangheng14@huawei.com>
Date: Thu, 7 Jul 2022 21:31:20 +0800
Subject: [PATCH 6/6] refactor-pkt-read-send-performance
---
src/common/dpdk_common.h | 145 +++++++
src/common/gazelle_dfx_msg.h | 50 ++-
src/lstack/api/lstack_epoll.c | 321 ++++++--------
src/lstack/api/lstack_wrap.c | 15 +-
src/lstack/core/lstack_cfg.c | 18 +
src/lstack/core/lstack_control_plane.c | 4 +-
src/lstack/core/lstack_dpdk.c | 32 +-
src/lstack/core/lstack_init.c | 5 +-
src/lstack/core/lstack_lwip.c | 477 ++++++++++-----------
src/lstack/core/lstack_protocol_stack.c | 276 ++++++------
src/lstack/core/lstack_stack_stat.c | 80 +++-
src/lstack/core/lstack_thread_rpc.c | 85 ++--
src/lstack/include/lstack_cfg.h | 1 +
src/lstack/include/lstack_dpdk.h | 5 +-
src/lstack/include/lstack_lockless_queue.h | 10 +-
src/lstack/include/lstack_lwip.h | 11 +-
src/lstack/include/lstack_protocol_stack.h | 31 +-
src/lstack/include/lstack_stack_stat.h | 3 +
src/lstack/include/lstack_thread_rpc.h | 5 +-
src/lstack/include/posix/lstack_epoll.h | 22 +-
src/lstack/lstack.conf | 1 +
src/lstack/netif/lstack_ethdev.c | 9 +-
src/lstack/netif/lstack_vdev.c | 14 +-
src/ltran/ltran_dfx.c | 52 ++-
src/ltran/ltran_forward.c | 18 +-
src/ltran/ltran_stat.c | 19 +-
26 files changed, 911 insertions(+), 798 deletions(-)
diff --git a/src/common/dpdk_common.h b/src/common/dpdk_common.h
index 595e85f..4a7bd37 100644
--- a/src/common/dpdk_common.h
+++ b/src/common/dpdk_common.h
@@ -14,6 +14,7 @@
#define __GAZELLE_DPDK_COMMON_H__
#include <rte_mbuf.h>
+#include <rte_ring.h>
#define GAZELLE_KNI_NAME "kni" // will be removed during dpdk update
@@ -35,6 +36,7 @@ static __rte_always_inline void copy_mbuf(struct rte_mbuf *dst, struct rte_mbuf
return;
dst->ol_flags = src->ol_flags;
+ dst->tx_offload = src->tx_offload;
// there is buf_len in rx_descriptor_fields1, copy it is dangerous acturely. 16 : mbuf desc size
rte_memcpy((uint8_t *)dst->rx_descriptor_fields1, (const uint8_t *)src->rx_descriptor_fields1, 16);
@@ -65,4 +67,147 @@ int32_t dpdk_kni_init(uint16_t port, struct rte_mempool *pool);
int32_t kni_process_tx(struct rte_mbuf **pkts_burst, uint32_t count);
void kni_process_rx(uint16_t port);
+/*
+ gazelle custom rte ring interface
+ lightweight ring reduce atomic and smp_mb.
+ only surpport single-consumers or the single-consumer.
+ */
+static __rte_always_inline uint32_t gazelle_light_ring_enqueue_busrt(struct rte_ring *r, void **obj_table, uint32_t n)
+{
+ uint32_t cons = __atomic_load_n(&r->cons.tail, __ATOMIC_ACQUIRE);
+ uint32_t prod = r->prod.tail;
+ uint32_t free_entries = r->capacity + cons - prod;
+
+ if (n > free_entries) {
+ return 0;
+ }
+
+ __rte_ring_enqueue_elems(r, prod, obj_table, sizeof(void *), n);
+
+ __atomic_store_n(&r->prod.tail, prod + n, __ATOMIC_RELEASE);
+
+ return n;
+}
+
+static __rte_always_inline uint32_t gazelle_light_ring_dequeue_burst(struct rte_ring *r, void **obj_table, uint32_t n)
+{
+ uint32_t prod = __atomic_load_n(&r->prod.tail, __ATOMIC_ACQUIRE);
+ uint32_t cons = r->cons.tail;
+ uint32_t entries = prod - cons;
+
+ if (n > entries) {
+ n = entries;
+ }
+
+ if (n == 0) {
+ return 0;
+ }
+
+ __rte_ring_dequeue_elems(r, cons, obj_table, sizeof(void *), n);
+
+ __atomic_store_n(&r->cons.tail, cons + n, __ATOMIC_RELEASE);
+
+ return n;
+}
+
+/*
+ gazelle custom rte ring interface
+ one thread enqueue and dequeue, other thread read object use and object still in queue.
+ so malloc and free in same thread. only surpport single-consumers or the single-consumer.
+
+ cons.tail prod.tail prod.head cons.head
+ gazelle_ring_sp_enqueue: cons.head-->> cons.tal, enqueue object
+ gazelle_ring_sc_dequeue: cons.tal -->> prod.tail, dequeue object
+ gazelle_ring_read: prod.tail-->> cons.head, read object, prod.head = prod.tail + N
+ gazelle_ring_read_over: prod.tail = prod.head, update prod.tail
+ */
+static __rte_always_inline uint32_t gazelle_ring_sp_enqueue(struct rte_ring *r, void **obj_table, uint32_t n)
+{
+ uint32_t head = __atomic_load_n(&r->cons.head, __ATOMIC_ACQUIRE);
+ uint32_t tail = __atomic_load_n(&r->cons.tail, __ATOMIC_ACQUIRE);
+
+ uint32_t entries = r->capacity + tail - head;
+ if (n > entries) {
+ return 0;
+ }
+
+
+ __rte_ring_enqueue_elems(r, head, obj_table, sizeof(void *), n);
+
+ __atomic_store_n(&r->cons.head, head + n, __ATOMIC_RELEASE);
+
+ return n;
+}
+
+static __rte_always_inline uint32_t gazelle_ring_sc_dequeue(struct rte_ring *r, void **obj_table, uint32_t n)
+{
+ uint32_t cons = __atomic_load_n(&r->cons.tail, __ATOMIC_ACQUIRE);
+ uint32_t prod = __atomic_load_n(&r->prod.tail, __ATOMIC_ACQUIRE);
+
+ uint32_t entries = prod - cons;
+ if (n > entries) {
+ n = entries;
+ }
+ if (unlikely(n == 0)) {
+ return 0;
+ }
+
+
+ __rte_ring_dequeue_elems(r, cons, obj_table, sizeof(void *), n);
+
+ __atomic_store_n(&r->cons.tail, cons + n, __ATOMIC_RELEASE);
+
+ return n;
+}
+
+static __rte_always_inline uint32_t gazelle_ring_read(struct rte_ring *r, void **obj_table, uint32_t n)
+{
+ uint32_t cons = __atomic_load_n(&r->cons.head, __ATOMIC_ACQUIRE);
+ uint32_t prod = r->prod.head;
+
+ const uint32_t entries = cons - prod;
+ if (n > entries) {
+ n = entries;
+ }
+ if (unlikely(n == 0)) {
+ return 0;
+ }
+
+ __rte_ring_dequeue_elems(r, prod, obj_table, sizeof(void *), n);
+
+ r->prod.head = prod + n;
+
+ return n;
+}
+
+static __rte_always_inline void gazelle_ring_read_n(struct rte_ring *r, uint32_t n)
+{
+ __atomic_store_n(&r->prod.tail, r->prod.tail + n, __ATOMIC_RELEASE);
+}
+
+static __rte_always_inline void gazelle_ring_read_over(struct rte_ring *r)
+{
+ __atomic_store_n(&r->prod.tail, r->prod.head, __ATOMIC_RELEASE);
+}
+
+static __rte_always_inline uint32_t gazelle_ring_readover_count(struct rte_ring *r)
+{
+ rte_smp_rmb();
+ return r->prod.tail - r->cons.tail;
+}
+static __rte_always_inline uint32_t gazelle_ring_readable_count(const struct rte_ring *r)
+{
+ rte_smp_rmb();
+ return r->cons.head - r->prod.tail;
+}
+
+static __rte_always_inline uint32_t gazelle_ring_count(const struct rte_ring *r)
+{
+ rte_smp_rmb();
+ return r->cons.head - r->cons.tail;
+}
+static __rte_always_inline uint32_t gazelle_ring_free_count(const struct rte_ring *r)
+{
+ return r->capacity - gazelle_ring_count(r);
+}
#endif
diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h
index 6db67ee..cf435cd 100644
--- a/src/common/gazelle_dfx_msg.h
+++ b/src/common/gazelle_dfx_msg.h
@@ -57,34 +57,37 @@ enum GAZELLE_LATENCY_TYPE {
GAZELLE_LATENCY_READ,
};
-struct gazelle_stat_pkts {
- uint64_t tx;
- uint64_t rx;
- uint64_t tx_drop;
- uint64_t rx_drop;
- uint64_t rx_allocmbuf_fail;
- uint64_t tx_allocmbuf_fail;
- uint64_t call_msg_cnt;
- uint16_t conn_num;
- uint16_t send_idle_ring_cnt;
- uint64_t event_list;
+struct gazelle_stack_stat {
+ uint64_t wakeup_events;
+ uint64_t write_lwip_cnt;
+ uint64_t send_self_rpc;
uint64_t read_lwip_drop;
uint64_t read_lwip_cnt;
- uint64_t write_lwip_drop;
- uint64_t write_lwip_cnt;
+ uint64_t rx_allocmbuf_fail;
+ uint64_t tx_allocmbuf_fail;
+ uint64_t call_null;
+ uint64_t rx_drop;
+ uint64_t rx;
+ uint64_t tx_drop;
+ uint64_t tx;
+};
+
+struct gazelle_wakeup_stat {
+ uint64_t app_events;
+ uint64_t app_write_idlefail;
uint64_t app_write_cnt;
uint64_t app_read_cnt;
- uint64_t app_write_idlefail;
- uint64_t app_write_drop;
- uint64_t recv_list;
- uint64_t wakeup_events;
- uint64_t app_events;
- uint64_t call_alloc_fail;
uint64_t read_null;
- uint64_t call_null;
- uint64_t arp_copy_fail;
- uint64_t send_self_rpc;
- uint64_t send_list;
+};
+
+struct gazelle_stat_pkts {
+ uint64_t call_msg_cnt;
+ uint16_t conn_num;
+ uint64_t recv_list_cnt;
+ uint64_t call_alloc_fail;
+ uint64_t send_list_cnt;
+ struct gazelle_stack_stat stack_stat;
+ struct gazelle_wakeup_stat wakeup_stat;
};
/* same as define in lwip/stats.h - struct stats_mib2 */
@@ -159,6 +162,7 @@ struct gazelle_stat_lstack_conn_info {
uint32_t recv_ring_cnt;
uint32_t tcp_sub_state;
int32_t sem_cnt;
+ int32_t fd;
};
struct gazelle_stat_lstack_conn {
diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c
index cba67ea..4978f02 100644
--- a/src/lstack/api/lstack_epoll.c
+++ b/src/lstack/api/lstack_epoll.c
@@ -16,6 +16,7 @@
#include <time.h>
#include <poll.h>
#include <stdatomic.h>
+#include <pthread.h>
#include <lwip/lwipsock.h>
#include <lwip/sockets.h>
@@ -39,36 +40,33 @@
#define SEC_TO_NSEC 1000000000
#define SEC_TO_MSEC 1000
#define MSEC_TO_NSEC 1000000
-#define EPOLL_MAX_EVENTS 512
#define POLL_KERNEL_EVENTS 32
-static PER_THREAD struct wakeup_poll g_wakeup_poll = {0};
-static bool g_use_epoll = false; /* FIXME: when no epoll close prepare event for performance testing */
-
void add_epoll_event(struct netconn *conn, uint32_t event)
{
/* conn sock nerver null, because lwip call this func */
- struct lwip_sock *sock = get_socket(conn->socket);
-
- if ((event & sock->epoll_events) == 0) {
+ struct lwip_sock *sock = get_socket_by_fd(conn->socket);
+ if (sock->wakeup == NULL || (event & sock->epoll_events) == 0) {
return;
}
+ struct wakeup_poll *wakeup = sock->wakeup;
+ struct protocol_stack *stack = sock->stack;
- sock->events |= event & sock->epoll_events;
-
-#ifdef GAZELLE_USE_EPOLL_EVENT_STACK
- if (g_use_epoll && list_is_empty(&sock->event_list)) {
- list_add_node(&sock->stack->event_list, &sock->event_list);
+ if (wakeup->type == WAKEUP_EPOLL) {
+ pthread_spin_lock(&wakeup->event_list_lock);
+ sock->events |= (event == EPOLLERR) ? (EPOLLIN | EPOLLERR) : (event & sock->epoll_events);
+ if (list_is_null(&sock->event_list)) {
+ list_add_node(&wakeup->event_list, &sock->event_list);
+ }
+ pthread_spin_unlock(&wakeup->event_list_lock);
}
-#endif
- if (sock->wakeup) {
- sock->stack->stats.wakeup_events++;
- if (get_protocol_stack_group()->wakeup_enable) {
- rte_ring_sp_enqueue(sock->stack->wakeup_ring, &sock->wakeup->event_sem);
- } else {
- sem_post(&sock->wakeup->event_sem);
- }
+ stack->stats.wakeup_events++;
+ sem_t *sem = &wakeup->event_sem;
+ if (get_protocol_stack_group()->wakeup_enable) {
+ gazelle_light_ring_enqueue_busrt(stack->wakeup_ring, (void **)&sem, 1);
+ } else {
+ sem_post(sem);
}
}
@@ -77,61 +75,34 @@ static inline uint32_t update_events(struct lwip_sock *sock)
uint32_t event = 0;
if (sock->epoll_events & EPOLLIN) {
- if (sock->attach_fd > 0 && NETCONN_IS_ACCEPTIN(sock)) {
- event |= EPOLLIN;
- }
-
- if (sock->attach_fd < 0 && NETCONN_IS_DATAIN(sock)) {
+ if (NETCONN_IS_DATAIN(sock) || NETCONN_IS_ACCEPTIN(sock)) {
event |= EPOLLIN;
}
}
if ((sock->epoll_events & EPOLLOUT) && NETCONN_IS_OUTIDLE(sock)) {
- event |= EPOLLOUT;
+ /* lwip_netconn_do_connected set LIBOS FLAGS when connected */
+ if (sock->conn && CONN_TYPE_IS_LIBOS(sock->conn)) {
+ event |= EPOLLOUT;
+ }
}
- if ((sock->epoll_events & EPOLLERR) && (sock->events & EPOLLERR)) {
+ if (sock->errevent > 0) {
event |= EPOLLERR | EPOLLIN;
}
return event;
}
-#ifdef GAZELLE_USE_EPOLL_EVENT_STACK
-void update_stack_events(struct protocol_stack *stack)
+static void raise_pending_events(struct wakeup_poll *wakeup, struct lwip_sock *sock)
{
- if (!g_use_epoll) {
- return;
- }
-
- struct list_node *node, *temp;
- list_for_each_safe(node, temp, &stack->event_list) {
- struct lwip_sock *sock = container_of(node, struct lwip_sock, event_list);
-
- sock->events = update_events(sock);
- if (sock->events != 0) {
- continue;
- }
-
- if (pthread_spin_trylock(&stack->event_lock)) {
- continue;
+ sock->events = update_events(sock);
+ if (sock->events) {
+ pthread_spin_lock(&wakeup->event_list_lock);
+ if (list_is_null(&sock->event_list)) {
+ list_add_node(&wakeup->event_list, &sock->event_list);
}
- list_del_node_init(&sock->event_list);
- pthread_spin_unlock(&stack->event_lock);
- }
-}
-#endif
-
-static void raise_pending_events(struct lwip_sock *sock)
-{
- struct lwip_sock *attach_sock = (sock->attach_fd > 0) ? get_socket_by_fd(sock->attach_fd) : sock;
- if (attach_sock == NULL) {
- return;
- }
-
- attach_sock->events = update_events(attach_sock);
- if (attach_sock->events & attach_sock->epoll_events) {
- rpc_call_addevent(attach_sock->stack, attach_sock);
+ pthread_spin_unlock(&wakeup->event_list_lock);
}
}
@@ -157,11 +128,15 @@ int32_t lstack_epoll_create(int32_t size)
memset_s(wakeup, sizeof(struct wakeup_poll), 0, sizeof(struct wakeup_poll));
init_list_node(&wakeup->event_list);
- wakeup->epollfd = fd;
sem_init(&wakeup->event_sem, 0, 0);
+ pthread_spin_init(&wakeup->event_list_lock, PTHREAD_PROCESS_PRIVATE);
+
+ wakeup->type = WAKEUP_EPOLL;
+ wakeup->epollfd = fd;
sock->wakeup = wakeup;
- g_use_epoll = true;
+ register_wakeup(wakeup);
+
return fd;
}
@@ -176,6 +151,9 @@ int32_t lstack_epoll_close(int32_t fd)
}
if (sock->wakeup) {
+ unregister_wakeup(sock->wakeup);
+ sem_destroy(&sock->wakeup->event_sem);
+ pthread_spin_destroy(&sock->wakeup->event_list_lock);
free(sock->wakeup);
}
sock->wakeup = NULL;
@@ -236,161 +214,116 @@ int32_t lstack_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_even
struct lwip_sock *sock = get_socket(fd);
if (sock == NULL) {
- epoll_sock->wakeup->have_kernel_fd = true;
return posix_api->epoll_ctl_fn(epfd, op, fd, event);
}
if (CONN_TYPE_HAS_HOST(sock->conn)) {
- epoll_sock->wakeup->have_kernel_fd = true;
int32_t ret = posix_api->epoll_ctl_fn(epfd, op, fd, event);
if (ret < 0) {
- return ret;
+ LSTACK_LOG(ERR, LSTACK, "fd=%d epfd=%d op=%d\n", fd, epfd, op);
}
}
+ struct wakeup_poll *wakeup = epoll_sock->wakeup;
do {
switch (op) {
case EPOLL_CTL_ADD:
- sock->wakeup = epoll_sock->wakeup;
- if (sock->stack) {
- epoll_sock->wakeup->stack_fd_cnt[sock->stack->queue_id]++;
- }
- if (list_is_empty(&sock->event_list)) {
- list_add_node(&sock->wakeup->event_list, &sock->event_list);
- }
+ sock->wakeup = wakeup;
+ wakeup->stack_fd_cnt[sock->stack->queue_id]++;
/* fall through */
case EPOLL_CTL_MOD:
sock->epoll_events = event->events | EPOLLERR | EPOLLHUP;
sock->ep_data = event->data;
- if (sock->conn && NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
- raise_pending_events(sock);
- }
+ raise_pending_events(wakeup, sock);
break;
case EPOLL_CTL_DEL:
- list_del_node_init(&sock->event_list);
sock->epoll_events = 0;
- if (sock->stack) {
- epoll_sock->wakeup->stack_fd_cnt[sock->stack->queue_id]--;
- }
+ wakeup->stack_fd_cnt[sock->stack->queue_id]--;
+ pthread_spin_lock(&wakeup->event_list_lock);
+ list_del_node_null(&sock->event_list);
+ pthread_spin_unlock(&wakeup->event_list_lock);
break;
default:
GAZELLE_RETURN(EINVAL);
}
- fd = sock->nextfd;
- sock = get_socket(fd);
- } while (fd > 0 && sock != NULL);
+ sock = sock->listen_next;
+ } while (sock != NULL);
- update_epoll_max_stack(epoll_sock->wakeup);
+ update_epoll_max_stack(wakeup);
return 0;
}
-#ifdef GAZELLE_USE_EPOLL_EVENT_STACK
-static int32_t epoll_lwip_event(struct wakeup_poll *wakeup, struct epoll_event *events, uint32_t maxevents)
+static void del_node_array(struct epoll_event *events, int32_t event_num, int32_t del_index)
{
- int32_t event_num = 0;
- struct protocol_stack_group *stack_group = get_protocol_stack_group();
-
- maxevents = LWIP_MIN(EPOLL_MAX_EVENTS, maxevents);
- for (uint32_t i = 0; i < stack_group->stack_num && event_num < maxevents; i++) {
- struct protocol_stack *stack = stack_group->stacks[i];
- int32_t start_event_num = event_num;
-
- if (pthread_spin_trylock(&stack->event_lock)) {
- continue;
- }
-
- struct list_node *node, *temp;
- list_for_each_safe(node, temp, &stack->event_list) {
- struct lwip_sock *sock = container_of(node, struct lwip_sock, event_list);
-
- uint32_t event = sock->events & sock->epoll_events;
- if (event == 0 || sock->wait_close) {
- continue;
- }
-
- events[event_num].events = event;
- events[event_num].data = sock->ep_data;
- event_num++;
+ for (int32_t i = del_index; i + 1 < event_num; i++) {
+ events[i] = events[i + 1];
+ }
+}
- if (event_num >= maxevents) {
- break;
+static int32_t del_duplicate_event(struct epoll_event *events, int32_t event_num)
+{
+ for (int32_t i = 0; i < event_num; i++) {
+ for (int32_t j = i + 1; j < event_num; j++) {
+ if (events[i].data.u64 == events[j].data.u64) {
+ del_node_array(events, event_num, j);
+ event_num--;
}
}
-
- pthread_spin_unlock(&stack->event_lock);
-
- __sync_fetch_and_add(&stack->stats.app_events, event_num - start_event_num);
}
return event_num;
}
-#else
+
static int32_t epoll_lwip_event(struct wakeup_poll *wakeup, struct epoll_event *events, uint32_t maxevents)
{
int32_t event_num = 0;
struct list_node *node, *temp;
+ int32_t accept_num = 0;
+
+ pthread_spin_lock(&wakeup->event_list_lock);
+
list_for_each_safe(node, temp, &wakeup->event_list) {
struct lwip_sock *sock = container_of(node, struct lwip_sock, event_list);
- if (sock->conn == NULL) {
- list_del_node_init(&sock->event_list);
- continue;
+ if (sock->conn && sock->conn->acceptmbox) {
+ accept_num++;
}
- struct lwip_sock *temp_sock = sock;
- do {
- struct lwip_sock *attach_sock = (temp_sock->attach_fd > 0) ? get_socket(temp_sock->attach_fd) : temp_sock;
- if (attach_sock == NULL || temp_sock->wait_close) {
- temp_sock = (temp_sock->nextfd > 0) ? get_socket(temp_sock->nextfd) : NULL;
- continue;
- }
+ events[event_num].events = sock->events;
+ events[event_num].data = sock->ep_data;
+ event_num++;
- uint32_t event = update_events(attach_sock);
- if (event != 0) {
- events[event_num].events = event;
- events[event_num].data = temp_sock->ep_data;
- event_num++;
- if (event_num >= maxevents) {
- break;
- }
- }
+ if (event_num >= maxevents) {
+ break;
+ }
+ }
- temp_sock = (temp_sock->nextfd > 0) ? get_socket(temp_sock->nextfd) : NULL;
- } while (temp_sock);
+ pthread_spin_unlock(&wakeup->event_list_lock);
+
+ if (accept_num > 1) {
+ event_num = del_duplicate_event(events, event_num);
}
+ // atomic_fetch_add(&wakeup->bind_stack->stats.app_events, event_num);
return event_num;
}
-#endif
static int32_t poll_lwip_event(struct pollfd *fds, nfds_t nfds)
{
int32_t event_num = 0;
for (uint32_t i = 0; i < nfds; i++) {
- /* listenfd nextfd pointerto next stack listen, others nextfd=-1 */
+ /* sock->listen_next pointerto next stack listen */
int32_t fd = fds[i].fd;
- while (fd > 0) {
- struct lwip_sock *sock = get_socket(fd);
- if (sock == NULL) {
- break;
- }
-
- /* attach listen is empty, all event in attached listen. attached listen attach_fd is self */
- struct lwip_sock *attach_sock = (sock->attach_fd > 0) ? get_socket(sock->attach_fd) : sock;
- if (attach_sock == NULL || sock->wait_close) {
- fd = sock->nextfd;
- continue;
- }
-
- uint32_t events = update_events(attach_sock);
+ struct lwip_sock *sock = get_socket_by_fd(fd);
+ while (sock && sock->conn) {
+ uint32_t events = update_events(sock);
if (events) {
fds[i].revents = events;
- __sync_fetch_and_add(&sock->stack->stats.app_events, 1);
event_num++;
break;
}
- fd = sock->nextfd;
+ sock = sock->listen_next;;
}
}
@@ -417,7 +350,7 @@ static void change_epollfd_kernel_thread(struct wakeup_poll *wakeup, struct prot
/* avoid kernel thread post too much, use EPOLLET */
struct epoll_event event;
- event.data.ptr = &wakeup->event_sem;
+ event.data.ptr = wakeup;
event.events = EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLET;
if (posix_api->epoll_ctl_fn(new_stack->epollfd, EPOLL_CTL_ADD, wakeup->epollfd, &event) != 0) {
LSTACK_LOG(ERR, LSTACK, "epoll_ctl_fn errno=%d\n", errno);
@@ -457,15 +390,18 @@ int32_t lstack_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxe
do {
event_num += epoll_lwip_event(sock->wakeup, &events[event_num], maxevents - event_num);
+ sock->wakeup->stat.app_events += event_num;
- if (sock->wakeup->have_kernel_fd) {
+ if (__atomic_load_n(&sock->wakeup->have_kernel_event, __ATOMIC_RELAXED)) {
event_num += posix_api->epoll_wait_fn(epfd, &events[event_num], maxevents - event_num, 0);
}
if (event_num > 0) {
+ while (sem_trywait(&sock->wakeup->event_sem) == 0);
break;
}
+ sock->wakeup->have_kernel_event = false;
if (timeout < 0) {
ret = sem_wait(&sock->wakeup->event_sem);
} else {
@@ -479,6 +415,7 @@ int32_t lstack_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxe
static void init_poll_wakeup_data(struct wakeup_poll *wakeup)
{
sem_init(&wakeup->event_sem, 0, 0);
+ wakeup->type = WAKEUP_POLL;
wakeup->last_fds = calloc(POLL_KERNEL_EVENTS, sizeof(struct pollfd));
if (wakeup->last_fds == NULL) {
@@ -542,11 +479,6 @@ static void update_kernel_poll(struct wakeup_poll *wakeup, uint32_t index, struc
if (posix_api->epoll_ctl_fn(wakeup->epollfd, EPOLL_CTL_ADD, new_fd->fd, &event) != 0) {
LSTACK_LOG(ERR, LSTACK, "epoll_ctl_fn errno=%d\n", errno);
}
-
- wakeup->last_fds[index].fd = new_fd->fd;
- wakeup->last_fds[index].events = new_fd->events;
-
- wakeup->have_kernel_fd = true;
}
static void poll_init(struct wakeup_poll *wakeup, struct pollfd *fds, nfds_t nfds)
@@ -554,17 +486,17 @@ static void poll_init(struct wakeup_poll *wakeup, struct pollfd *fds, nfds_t nfd
if (!wakeup->init) {
wakeup->init = true;
init_poll_wakeup_data(wakeup);
- } else {
- while (sem_trywait(&wakeup->event_sem) == 0) {}
- }
-
- if (nfds > wakeup->last_max_nfds) {
- resize_kernel_poll(wakeup, nfds);
+ register_wakeup(wakeup);
}
int32_t stack_count[PROTOCOL_STACK_MAX] = {0};
int32_t poll_change = 0;
+ /* poll fds num more, recalloc fds size */
+ if (nfds > wakeup->last_max_nfds) {
+ resize_kernel_poll(wakeup, nfds);
+ poll_change = 1;
+ }
/* poll fds num less, del old fd */
for (uint32_t i = nfds; i < wakeup->last_nfds; i++) {
update_kernel_poll(wakeup, i, NULL);
@@ -572,44 +504,51 @@ static void poll_init(struct wakeup_poll *wakeup, struct pollfd *fds, nfds_t nfd
}
for (uint32_t i = 0; i < nfds; i++) {
+ int32_t fd = fds[i].fd;
fds[i].revents = 0;
+ struct lwip_sock *sock = get_socket_by_fd(fd);
- if (fds[i].fd == wakeup->last_fds[i].fd && fds[i].events == wakeup->last_fds[i].events) {
- continue;
+ if (fd == wakeup->last_fds[i].fd && fds[i].events == wakeup->last_fds[i].events) {
+ /* fd close then socket may get same fd. */
+ if (sock == NULL || sock->wakeup != NULL) {
+ continue;
+ }
}
+ wakeup->last_fds[i].fd = fd;
+ wakeup->last_fds[i].events = fds[i].events;
poll_change = 1;
- int32_t fd = fds[i].fd;
- struct lwip_sock *sock = get_socket(fd);
- if (sock == NULL || CONN_TYPE_HAS_HOST(sock->conn)) {
+ if (sock == NULL || sock->conn == NULL || CONN_TYPE_HAS_HOST(sock->conn)) {
update_kernel_poll(wakeup, i, fds + i);
}
- do {
- sock = get_socket(fd);
- if (sock == NULL || sock->conn == NULL) {
- break;
+ while (sock && sock->conn) {
+ if (sock->epoll_events != (fds[i].events | POLLERR)) {
+ sock->epoll_events = fds[i].events | POLLERR;
+ }
+ if (sock->wakeup != wakeup) {
+ sock->wakeup = wakeup;
}
- sock->epoll_events = fds[i].events | POLLERR;
- sock->wakeup = wakeup;
- /* listenfd list */
- fd = sock->nextfd;
stack_count[sock->stack->queue_id]++;
- } while (fd > 0);
+ /* listenfd list */
+ sock = sock->listen_next;
+ }
}
- wakeup->last_nfds = nfds;
if (poll_change == 0) {
return;
}
+ wakeup->last_nfds = nfds;
poll_bind_statck(wakeup, stack_count);
}
int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout)
{
- poll_init(&g_wakeup_poll, fds, nfds);
+ static PER_THREAD struct wakeup_poll wakeup_poll = {0};
+
+ poll_init(&wakeup_poll, fds, nfds);
int32_t event_num = 0;
int32_t ret;
@@ -624,23 +563,25 @@ int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout)
event_num += poll_lwip_event(fds, nfds);
/* reduce syscall epoll_wait */
- if (g_wakeup_poll.have_kernel_fd) {
- int32_t kernel_num = posix_api->epoll_wait_fn(g_wakeup_poll.epollfd, g_wakeup_poll.events, nfds, 0);
+ if (__atomic_load_n(&wakeup_poll.have_kernel_event, __ATOMIC_RELAXED)) {
+ int32_t kernel_num = posix_api->epoll_wait_fn(wakeup_poll.epollfd, wakeup_poll.events, nfds, 0);
for (int32_t i = 0; i < kernel_num; i++) {
- uint32_t index = g_wakeup_poll.events[i].data.u32;
- fds[index].revents = g_wakeup_poll.events[i].events;
+ uint32_t index = wakeup_poll.events[i].data.u32;
+ fds[index].revents = wakeup_poll.events[i].events;
}
event_num += kernel_num >= 0 ? kernel_num : 0;
}
if (event_num > 0) {
+ while (sem_trywait(&wakeup_poll.event_sem) == 0);
break;
}
+ wakeup_poll.have_kernel_event = false;
if (timeout < 0) {
- ret = sem_wait(&g_wakeup_poll.event_sem);
+ ret = sem_wait(&wakeup_poll.event_sem);
} else {
- ret = sem_timedwait(&g_wakeup_poll.event_sem, &poll_time);
+ ret = sem_timedwait(&wakeup_poll.event_sem, &poll_time);
}
} while (ret == 0);
diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c
index bf5dcb4..ec68d62 100644
--- a/src/lstack/api/lstack_wrap.c
+++ b/src/lstack/api/lstack_wrap.c
@@ -52,7 +52,7 @@ static inline enum KERNEL_LWIP_PATH select_path(int fd)
return PATH_KERNEL;
}
- if (unlikely(posix_api->is_chld)) {
+ if (unlikely(posix_api->ues_posix)) {
return PATH_KERNEL;
}
@@ -84,7 +84,7 @@ static inline int32_t do_epoll_create(int32_t size)
return posix_api->epoll_create_fn(size);
}
- if (unlikely(posix_api->is_chld)) {
+ if (unlikely(posix_api->ues_posix)) {
return posix_api->epoll_create_fn(size);
}
@@ -93,7 +93,7 @@ static inline int32_t do_epoll_create(int32_t size)
static inline int32_t do_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event* event)
{
- if (unlikely(posix_api->is_chld)) {
+ if (unlikely(posix_api->ues_posix)) {
return posix_api->epoll_ctl_fn(epfd, op, fd, event);
}
@@ -102,7 +102,7 @@ static inline int32_t do_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct
static inline int32_t do_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout)
{
- if (unlikely(posix_api->is_chld)) {
+ if (unlikely(posix_api->ues_posix)) {
return posix_api->epoll_wait_fn(epfd, events, maxevents, timeout);
}
@@ -203,7 +203,8 @@ static inline int32_t do_listen(int32_t s, int32_t backlog)
return posix_api->listen_fn(s, backlog);
}
- int32_t ret = stack_broadcast_listen(s, backlog);
+ int32_t ret = get_global_cfg_params()->listen_shadow ? stack_broadcast_listen(s, backlog) :
+ stack_single_listen(s, backlog);
if (ret != 0) {
return ret;
}
@@ -264,7 +265,7 @@ static inline int32_t do_setsockopt(int32_t s, int32_t level, int32_t optname, c
static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol)
{
if ((domain != AF_INET && domain != AF_UNSPEC)
- || posix_api->is_chld) {
+ || posix_api->ues_posix) {
return posix_api->socket_fn(domain, type, protocol);
}
@@ -368,7 +369,7 @@ static int32_t do_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout)
GAZELLE_RETURN(EINVAL);
}
- if (unlikely(posix_api->is_chld) || nfds == 0) {
+ if (unlikely(posix_api->ues_posix) || nfds == 0) {
return posix_api->poll_fn(fds, nfds, timeout);
}
diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c
index 13086a3..ca2b979 100644
--- a/src/lstack/core/lstack_cfg.c
+++ b/src/lstack/core/lstack_cfg.c
@@ -56,6 +56,7 @@ static int32_t parse_devices(void);
static int32_t parse_dpdk_args(void);
static int32_t parse_gateway_addr(void);
static int32_t parse_kni_switch(void);
+static int32_t parse_listen_shadow(void);
struct config_vector_t {
const char *name;
@@ -73,6 +74,7 @@ static struct config_vector_t g_config_tbl[] = {
{ "num_wakeup", parse_wakeup_cpu_number },
{ "low_power_mode", parse_low_power_mode },
{ "kni_switch", parse_kni_switch },
+ { "listen_shadow", parse_listen_shadow },
{ NULL, NULL }
};
@@ -670,6 +672,22 @@ static int32_t parse_use_ltran(void)
return 0;
}
+static int32_t parse_listen_shadow(void)
+{
+ const config_setting_t *arg = NULL;
+
+ arg = config_lookup(&g_config, "listen_shadow");
+ if (arg == NULL) {
+ g_config_params.listen_shadow = false;
+ return 0;
+ }
+
+ int32_t val = config_setting_get_int(arg);
+ g_config_params.listen_shadow = (val == 0) ? false : true;
+
+ return 0;
+}
+
static int32_t parse_kni_switch(void)
{
const config_setting_t *arg = NULL;
diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c
index 26a1b1c..ef38fb5 100644
--- a/src/lstack/core/lstack_control_plane.c
+++ b/src/lstack/core/lstack_control_plane.c
@@ -713,7 +713,7 @@ void control_server_thread(void *arg)
struct epoll_event evt_array;
while (1) {
/* wait init finish */
- if (posix_api->is_chld) {
+ if (posix_api->ues_posix) {
usleep(GAZELLE_10MS);
continue;
}
@@ -759,7 +759,7 @@ void control_client_thread(void *arg)
while (1) {
/* wait init finish */
- if (posix_api->is_chld) {
+ if (posix_api->ues_posix) {
usleep(GAZELLE_10MS);
continue;
}
diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c
index df0332b..6675d7b 100644
--- a/src/lstack/core/lstack_dpdk.c
+++ b/src/lstack/core/lstack_dpdk.c
@@ -129,26 +129,6 @@ static struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_
return pool;
}
-struct rte_mempool *create_rpc_mempool(const char *name, uint16_t queue_id)
-{
- char pool_name[PATH_MAX];
- struct rte_mempool *pool;
- int32_t ret;
-
- ret = snprintf_s(pool_name, sizeof(pool_name), PATH_MAX - 1, "%s_%hu", name, queue_id);
- if (ret < 0) {
- return NULL;
- }
-
- pool = rte_mempool_create(pool_name, CALL_POOL_SZ, sizeof(struct rpc_msg), 0, 0, NULL, NULL, NULL,
- NULL, rte_socket_id(), 0);
- if (pool == NULL) {
- LSTACK_LOG(ERR, LSTACK, "cannot create %s pool rte_err=%d\n", pool_name, rte_errno);
- }
-
- return pool;
-}
-
static struct reg_ring_msg *create_reg_mempool(const char *name, uint16_t queue_id)
{
int ret;
@@ -175,13 +155,13 @@ int32_t pktmbuf_pool_init(struct protocol_stack *stack, uint16_t stack_num)
return -1;
}
- stack->rx_pktmbuf_pool = create_pktmbuf_mempool("rx_mbuf", RX_NB_MBUF, RX_MBUF_CACHE_SZ,
+ stack->rx_pktmbuf_pool = create_pktmbuf_mempool("rx_mbuf", RX_NB_MBUF / stack_num, RX_MBUF_CACHE_SZ,
stack->queue_id);
if (stack->rx_pktmbuf_pool == NULL) {
return -1;
}
- stack->tx_pktmbuf_pool = create_pktmbuf_mempool("tx_mbuf", TX_NB_MBUF, TX_MBUF_CACHE_SZ,
+ stack->tx_pktmbuf_pool = create_pktmbuf_mempool("tx_mbuf", TX_NB_MBUF / stack_num, TX_MBUF_CACHE_SZ,
stack->queue_id);
if (stack->tx_pktmbuf_pool == NULL) {
return -1;
@@ -220,12 +200,14 @@ int32_t create_shared_ring(struct protocol_stack *stack)
lockless_queue_init(&stack->rpc_queue);
if (get_protocol_stack_group()->wakeup_enable) {
- stack->wakeup_ring = create_ring("WAKEUP_RING", VDEV_WAKEUP_QUEUE_SZ, 0, stack->queue_id);
+ stack->wakeup_ring = create_ring("WAKEUP_RING", VDEV_WAKEUP_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ,
+ stack->queue_id);
if (stack->wakeup_ring == NULL) {
return -1;
}
}
+
if (use_ltran()) {
stack->rx_ring = create_ring("RING_RX", VDEV_RX_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ, stack->queue_id);
if (stack->rx_ring == NULL) {
@@ -255,7 +237,7 @@ int32_t fill_mbuf_to_ring(struct rte_mempool *mempool, struct rte_ring *ring, ui
struct rte_mbuf *free_buf[FREE_RX_QUEUE_SZ];
while (remain > 0) {
- batch = LWIP_MIN(remain, FREE_RX_QUEUE_SZ);
+ batch = LWIP_MIN(remain, RING_SIZE(FREE_RX_QUEUE_SZ));
ret = gazelle_alloc_pktmbuf(mempool, free_buf, batch);
if (ret != 0) {
@@ -263,7 +245,7 @@ int32_t fill_mbuf_to_ring(struct rte_mempool *mempool, struct rte_ring *ring, ui
return -1;
}
- ret = rte_ring_en_enqueue_bulk(ring, (void **)free_buf, batch);
+ ret = gazelle_ring_sp_enqueue(ring, (void **)free_buf, batch);
if (ret == 0) {
LSTACK_LOG(ERR, LSTACK, "cannot enqueue to ring, count: %d\n", (int32_t)batch);
return -1;
diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c
index f8e96bf..78040b0 100644
--- a/src/lstack/core/lstack_init.c
+++ b/src/lstack/core/lstack_init.c
@@ -143,7 +143,7 @@ static int32_t check_preload_bind_proc(void)
__attribute__((destructor)) void gazelle_network_exit(void)
{
- if (posix_api != NULL && !posix_api->is_chld) {
+ if (posix_api != NULL && !posix_api->ues_posix) {
lwip_exit();
}
@@ -275,7 +275,6 @@ __attribute__((constructor)) void gazelle_network_init(void)
LSTACK_EXIT(1, "stack thread or kernel_event thread failed\n");
}
- posix_api->is_chld = 0;
+ posix_api->ues_posix = 0;
LSTACK_LOG(INFO, LSTACK, "gazelle_network_init success\n");
- rte_smp_mb();
}
diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c
index 8544ef7..156fc1f 100644
--- a/src/lstack/core/lstack_lwip.c
+++ b/src/lstack/core/lstack_lwip.c
@@ -35,33 +35,24 @@
#define HALF_DIVISOR (2)
#define USED_IDLE_WATERMARK (VDEV_IDLE_QUEUE_SZ >> 2)
-void listen_list_add_node(int32_t head_fd, int32_t add_fd)
-{
- struct lwip_sock *sock = NULL;
- int32_t fd = head_fd;
-
- while (fd > 0) {
- sock = get_socket(fd);
- if (sock == NULL) {
- LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null\n", get_stack_tid(), fd);
- return;
- }
- fd = sock->nextfd;
- }
- sock->nextfd = add_fd;
-}
+static int32_t lwip_alloc_pbufs(pbuf_layer layer, uint16_t length, pbuf_type type, void **pbufs, uint32_t num);
static void free_ring_pbuf(struct rte_ring *ring)
{
- while (1) {
- struct pbuf *pbuf = NULL;
- int32_t ret = rte_ring_sc_dequeue(ring, (void **)&pbuf);
- if (ret != 0) {
- break;
- }
+ void *pbufs[SOCK_RECV_RING_SIZE];
- pbuf_free(pbuf);
- }
+ do {
+ gazelle_ring_read(ring, pbufs, RING_SIZE(SOCK_RECV_RING_SIZE));
+ gazelle_ring_read_over(ring);
+ } while (gazelle_ring_readable_count(ring));
+
+ do {
+ uint32_t num = gazelle_ring_sc_dequeue(ring, pbufs, RING_SIZE(SOCK_RECV_RING_SIZE));
+
+ for (uint32_t i = 0; i < num; i++) {
+ pbuf_free(pbufs[i]);
+ }
+ } while (gazelle_ring_readover_count(ring));
}
static void reset_sock_data(struct lwip_sock *sock)
@@ -73,11 +64,6 @@ static void reset_sock_data(struct lwip_sock *sock)
}
sock->recv_ring = NULL;
- if (sock->recv_wait_free) {
- free_ring_pbuf(sock->recv_wait_free);
- rte_ring_free(sock->recv_wait_free);
- }
- sock->recv_wait_free = NULL;
if (sock->send_ring) {
free_ring_pbuf(sock->send_ring);
@@ -85,19 +71,11 @@ static void reset_sock_data(struct lwip_sock *sock)
}
sock->send_ring = NULL;
- if (sock->send_idle_ring) {
- free_ring_pbuf(sock->send_idle_ring);
- rte_ring_free(sock->send_idle_ring);
- }
- sock->send_idle_ring = NULL;
sock->stack = NULL;
sock->wakeup = NULL;
- sock->events = 0;
- sock->nextfd = -1;
- sock->attach_fd = -1;
+ sock->listen_next = NULL;
sock->wait_close = false;
- sock->shadowed_sock = NULL;
sock->epoll_events = 0;
sock->events = 0;
@@ -105,34 +83,29 @@ static void reset_sock_data(struct lwip_sock *sock)
pbuf_free(sock->recv_lastdata);
}
sock->recv_lastdata = NULL;
-
- if (sock->send_lastdata) {
- pbuf_free(sock->send_lastdata);
- }
- sock->send_lastdata = NULL;
}
static void replenish_send_idlembuf(struct rte_ring *ring)
{
- uint32_t replenish_cnt = rte_ring_free_count(ring);
+ void *pbuf[SOCK_SEND_RING_SIZE];
- for (uint32_t i = 0; i < replenish_cnt; i++) {
- struct pbuf *pbuf = lwip_alloc_pbuf(PBUF_TRANSPORT, TCP_MSS, PBUF_RAM);
- if (pbuf == NULL) {
- break;
- }
+ uint32_t replenish_cnt = gazelle_ring_free_count(ring);
+ uint32_t alloc_num = LWIP_MIN(replenish_cnt, RING_SIZE(SOCK_SEND_RING_SIZE));
- int32_t ret = rte_ring_sp_enqueue(ring, (void *)pbuf);
- if (ret < 0) {
- pbuf_free(pbuf);
- break;
- }
+ if (lwip_alloc_pbufs(PBUF_TRANSPORT, TCP_MSS, PBUF_RAM, (void **)pbuf, alloc_num) != 0) {
+ return;
+ }
+
+ uint32_t num = gazelle_ring_sp_enqueue(ring, pbuf, alloc_num);
+ for (uint32_t i = num; i < alloc_num; i++) {
+ pbuf_free(pbuf[i]);
}
}
void gazelle_init_sock(int32_t fd)
{
static uint32_t name_tick = 0;
+ struct protocol_stack *stack = get_protocol_stack();
struct lwip_sock *sock = get_socket(fd);
if (sock == NULL) {
return;
@@ -140,38 +113,26 @@ void gazelle_init_sock(int32_t fd)
reset_sock_data(sock);
- sock->recv_ring = create_ring("sock_recv", SOCK_RECV_RING_SIZE, 0, atomic_fetch_add(&name_tick, 1));
+ sock->recv_ring = create_ring("sock_recv", SOCK_RECV_RING_SIZE, RING_F_SP_ENQ | RING_F_SC_DEQ,
+ atomic_fetch_add(&name_tick, 1));
if (sock->recv_ring == NULL) {
LSTACK_LOG(ERR, LSTACK, "sock_recv create failed. errno: %d.\n", rte_errno);
return;
}
- sock->recv_wait_free = create_ring("wait_free", SOCK_RECV_RING_SIZE, 0, atomic_fetch_add(&name_tick, 1));
- if (sock->recv_wait_free == NULL) {
- LSTACK_LOG(ERR, LSTACK, "wait_free create failed. errno: %d.\n", rte_errno);
- return;
- }
-
- sock->send_ring = create_ring("sock_send", SOCK_SEND_RING_SIZE, 0, atomic_fetch_add(&name_tick, 1));
+ sock->send_ring = create_ring("sock_send", SOCK_SEND_RING_SIZE, RING_F_SP_ENQ | RING_F_SC_DEQ,
+ atomic_fetch_add(&name_tick, 1));
if (sock->send_ring == NULL) {
LSTACK_LOG(ERR, LSTACK, "sock_send create failed. errno: %d.\n", rte_errno);
return;
}
+ replenish_send_idlembuf(sock->send_ring);
- sock->send_idle_ring = create_ring("idle_send", SOCK_SEND_RING_SIZE, 0, atomic_fetch_add(&name_tick, 1));
- if (sock->send_idle_ring == NULL) {
- LSTACK_LOG(ERR, LSTACK, "idle_send create failed. errno: %d.\n", rte_errno);
- return;
- }
- replenish_send_idlembuf(sock->send_idle_ring);
-
- sock->stack = get_protocol_stack();
+ sock->stack = stack;
sock->stack->conn_num++;
- init_list_node(&sock->recv_list);
- init_list_node(&sock->attach_list);
- init_list_node(&sock->listen_list);
- init_list_node(&sock->event_list);
- init_list_node(&sock->send_list);
+ init_list_node_null(&sock->recv_list);
+ init_list_node_null(&sock->event_list);
+ init_list_node_null(&sock->send_list);
}
void gazelle_clean_sock(int32_t fd)
@@ -181,17 +142,18 @@ void gazelle_clean_sock(int32_t fd)
return;
}
+ if (sock->wakeup && sock->wakeup->type == WAKEUP_EPOLL) {
+ pthread_spin_lock(&sock->wakeup->event_list_lock);
+ list_del_node_null(&sock->event_list);
+ pthread_spin_unlock(&sock->wakeup->event_list_lock);
+ }
+
sock->stack->conn_num--;
reset_sock_data(sock);
- list_del_node_init(&sock->recv_list);
- list_del_node_init(&sock->attach_list);
- list_del_node_init(&sock->listen_list);
-#ifdef GAZELLE_USE_EPOLL_EVENT_STACK
- list_del_node_init(&sock->event_list);
-#endif
- list_del_node_init(&sock->send_list);
+ list_del_node_null(&sock->recv_list);
+ list_del_node_null(&sock->send_list);
}
void gazelle_free_pbuf(struct pbuf *pbuf)
@@ -201,45 +163,14 @@ void gazelle_free_pbuf(struct pbuf *pbuf)
}
struct rte_mbuf *mbuf = pbuf_to_mbuf(pbuf);
- if (mbuf->pool != NULL) {
- rte_pktmbuf_free(mbuf);
- } else {
- rte_free(mbuf);
- }
-}
-
-static int32_t alloc_mbufs(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num)
-{
- // alloc mbuf from pool
- if (rte_pktmbuf_alloc_bulk(pool, mbufs, num) == 0) {
- return 0;
- }
-
- // alloc mbuf from system
- for (uint32_t i = 0; i < num; i++) {
- struct rte_mbuf *mbuf = (struct rte_mbuf *)rte_malloc(NULL, pool->elt_size, sizeof(uint64_t));
- if (mbuf == NULL) {
- for (uint32_t j = 0; j < i; j++) {
- rte_free(mbufs[j]);
- mbufs[j] = NULL;
- }
- return -1;
- }
-
- mbufs[i] = mbuf;
- rte_pktmbuf_init(pool, NULL, mbuf, 0);
- rte_pktmbuf_reset(mbuf);
- mbuf->pool = NULL;
- }
-
- return 0;
+ rte_pktmbuf_free(mbuf);
}
int32_t gazelle_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num)
{
struct pbuf_custom *pbuf_custom = NULL;
- int32_t ret = alloc_mbufs(pool, mbufs, num);
+ int32_t ret = rte_pktmbuf_alloc_bulk(pool, mbufs, num);
if (ret != 0) {
return ret;
}
@@ -252,86 +183,98 @@ int32_t gazelle_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs,
return 0;
}
-struct pbuf *lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type type)
+static struct pbuf *init_mbuf_to_pbuf(struct rte_mbuf *mbuf, pbuf_layer layer, uint16_t length, pbuf_type type)
{
- struct rte_mbuf *mbuf;
- int32_t ret = alloc_mbufs(get_protocol_stack()->tx_pktmbuf_pool, &mbuf, 1);
- if (ret != 0) {
- get_protocol_stack()->stats.tx_allocmbuf_fail++;
- return NULL;
- }
-
struct pbuf_custom *pbuf_custom = mbuf_to_pbuf(mbuf);
pbuf_custom->custom_free_function = gazelle_free_pbuf;
void *data = rte_pktmbuf_mtod(mbuf, void *);
struct pbuf *pbuf = pbuf_alloced_custom(layer, length, type, pbuf_custom, data, MAX_PACKET_SZ);
-
-#if CHECKSUM_CHECK_IP_HW || CHECKSUM_CHECK_TCP_HW
if (pbuf) {
pbuf->ol_flags = 0;
pbuf->l2_len = 0;
pbuf->l3_len = 0;
}
-#endif
return pbuf;
}
-struct pbuf *write_lwip_data(struct lwip_sock *sock, uint16_t remain_size, uint8_t *apiflags)
+static int32_t lwip_alloc_pbufs(pbuf_layer layer, uint16_t length, pbuf_type type, void **bufs, uint32_t num)
{
- struct pbuf *pbuf = NULL;
+ int32_t ret = rte_pktmbuf_alloc_bulk(get_protocol_stack()->tx_pktmbuf_pool, (struct rte_mbuf **)bufs, num);
+ if (ret != 0) {
+ get_protocol_stack()->stats.tx_allocmbuf_fail++;
+ return -1;
+ }
- if (sock->send_lastdata) {
- pbuf = sock->send_lastdata;
- sock->send_lastdata = NULL;
- } else {
- int32_t ret = rte_ring_sc_dequeue(sock->send_ring, (void **)&pbuf);
- if (ret != 0) {
- *apiflags &= ~TCP_WRITE_FLAG_MORE;
- return NULL;
- }
+ for (uint32_t i = 0; i < num; i++) {
+ bufs[i] = init_mbuf_to_pbuf(bufs[i], layer, length, type);
}
- if (pbuf->tot_len >= remain_size) {
- sock->send_lastdata = pbuf;
- *apiflags |= TCP_WRITE_FLAG_MORE; /* set TCP_PSH flag */
+ return 0;
+}
+
+struct pbuf *lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type type)
+{
+ struct pbuf *pbuf;
+
+ if (lwip_alloc_pbufs(layer, length, type, (void **)&pbuf, 1) != 0) {
return NULL;
}
- replenish_send_idlembuf(sock->send_idle_ring);
+ return pbuf;
+}
- if ((sock->epoll_events & EPOLLOUT) && rte_ring_free_count(sock->send_ring)) {
- add_epoll_event(sock->conn, EPOLLOUT);
+struct pbuf *write_lwip_data(struct lwip_sock *sock, uint16_t remain_size, uint8_t *apiflags)
+{
+ struct pbuf *pbuf = NULL;
+
+ if (gazelle_ring_sc_dequeue(sock->send_ring, (void **)&pbuf, 1) != 1) {
+ *apiflags &= ~TCP_WRITE_FLAG_MORE;
+ return NULL;
}
sock->stack->stats.write_lwip_cnt++;
return pbuf;
}
+static inline void del_data_out_event(struct lwip_sock *sock)
+{
+ pthread_spin_lock(&sock->wakeup->event_list_lock);
+
+ /* check again avoid cover event add in stack thread */
+ if (!NETCONN_IS_OUTIDLE(sock)) {
+ sock->events &= ~EPOLLOUT;
+
+ if (sock->events == 0) {
+ list_del_node_null(&sock->event_list);
+ }
+ }
+
+ pthread_spin_unlock(&sock->wakeup->event_list_lock);
+}
+
ssize_t write_stack_data(struct lwip_sock *sock, const void *buf, size_t len)
{
- if (sock->events & EPOLLERR) {
+ if (sock->errevent > 0) {
return 0;
}
- uint32_t free_count = rte_ring_free_count(sock->send_ring);
+ uint32_t free_count = gazelle_ring_readable_count(sock->send_ring);
if (free_count == 0) {
return -1;
}
- uint32_t avaible_cont = rte_ring_count(sock->send_idle_ring);
- avaible_cont = LWIP_MIN(free_count, avaible_cont);
-
struct pbuf *pbuf = NULL;
ssize_t send_len = 0;
size_t copy_len;
uint32_t send_pkt = 0;
- while (send_len < len && send_pkt < avaible_cont) {
- int32_t ret = rte_ring_sc_dequeue(sock->send_idle_ring, (void **)&pbuf);
- if (ret < 0) {
- sock->stack->stats.app_write_idlefail++;
+ while (send_len < len && send_pkt < free_count) {
+ if (gazelle_ring_read(sock->send_ring, (void **)&pbuf, 1) != 1) {
+ if (sock->wakeup) {
+ sock->wakeup->stat.app_write_idlefail++;
+ }
break;
}
@@ -339,21 +282,42 @@ ssize_t write_stack_data(struct lwip_sock *sock, const void *buf, size_t len)
pbuf_take(pbuf, (char *)buf + send_len, copy_len);
pbuf->tot_len = pbuf->len = copy_len;
- ret = rte_ring_sp_enqueue(sock->send_ring, pbuf);
- if (ret != 0) {
- sock->stack->stats.app_write_drop++;
- pbuf_free(pbuf);
- break;
- }
-
send_len += copy_len;
send_pkt++;
}
- __sync_fetch_and_add(&sock->stack->stats.app_write_cnt, send_pkt);
+ gazelle_ring_read_over(sock->send_ring);
+
+ if (sock->wakeup) {
+ sock->wakeup->stat.app_write_cnt += send_pkt;
+ if (sock->wakeup->type == WAKEUP_EPOLL && (sock->events & EPOLLOUT)) {
+ del_data_out_event(sock);
+ }
+ }
return (send_len <= 0) ? -1 : send_len;
}
+static void do_lwip_send(int32_t fd, struct lwip_sock *sock, int32_t flags)
+{
+ /* send all send_ring, so len set lwip send max. */
+ ssize_t len = lwip_send(fd, sock, UINT16_MAX, flags);
+ if (len == 0) {
+ /* FIXME: should use POLLRDHUP, when connection be closed. lwip event-callback no POLLRDHUP */
+ sock->errevent = 1;
+ add_epoll_event(sock->conn, EPOLLERR);
+ }
+
+ if (gazelle_ring_readable_count(sock->send_ring) < SOCK_SEND_REPLENISH_THRES) {
+ replenish_send_idlembuf(sock->send_ring);
+ }
+
+ if (len > 0) {
+ if ((sock->epoll_events & EPOLLOUT) && NETCONN_IS_OUTIDLE(sock)) {
+ add_epoll_event(sock->conn, EPOLLOUT);
+ }
+ }
+}
+
void stack_send(struct rpc_msg *msg)
{
int32_t fd = msg->args[MSG_ARG_0].i;
@@ -369,17 +333,11 @@ void stack_send(struct rpc_msg *msg)
return;
}
- /* send all send_ring, so len set lwip send max. */
- ssize_t len = lwip_send(fd, sock, UINT16_MAX, flags);
- if (len == 0) {
- /* FIXME: should use POLLRDHUP, when connection be closed. lwip event-callback no POLLRDHUP */
- add_epoll_event(sock->conn, EPOLLERR);
- }
+ do_lwip_send(fd, sock, flags);
/* have remain data add sendlist */
if (NETCONN_IS_DATAOUT(sock)) {
- if (list_is_empty(&sock->send_list)) {
- sock->send_flags = flags;
+ if (list_is_null(&sock->send_list)) {
list_add_node(&sock->stack->send_list, &sock->send_list);
}
sock->stack->stats.send_self_rpc++;
@@ -396,20 +354,14 @@ void send_stack_list(struct protocol_stack *stack, uint32_t send_max)
sock = container_of(node, struct lwip_sock, send_list);
if (sock->conn == NULL || !NETCONN_IS_DATAOUT(sock)) {
- list_del_node_init(&sock->send_list);
+ list_del_node_null(&sock->send_list);
continue;
}
- /* send all send_ring, so len set lwip send max. */
- ssize_t len = lwip_send(sock->conn->socket, sock, UINT16_MAX, sock->send_flags);
- if (len == 0) {
- /* FIXME: should use POLLRDHUP, when connection be closed. lwip event-callback no POLLRDHUP */
- add_epoll_event(sock->conn, EPOLLERR);
- list_del_node_init(&sock->send_list);
- }
+ do_lwip_send(sock->conn->socket, sock, 0);
if (!NETCONN_IS_DATAOUT(sock)) {
- list_del_node_init(&sock->send_list);
+ list_del_node_null(&sock->send_list);
}
if (++read_num >= send_max) {
@@ -418,26 +370,39 @@ void send_stack_list(struct protocol_stack *stack, uint32_t send_max)
}
}
+static inline void free_recv_ring_readover(struct rte_ring *ring)
+{
+ void *pbufs[SOCK_RECV_RING_SIZE];
+ uint32_t num = gazelle_ring_sc_dequeue(ring, pbufs, RING_SIZE(SOCK_RECV_RING_SIZE));
+ for (uint32_t i = 0; i < num; i++) {
+ pbuf_free(pbufs[i]);
+ }
+}
+
ssize_t read_lwip_data(struct lwip_sock *sock, int32_t flags, u8_t apiflags)
{
if (sock->conn->recvmbox == NULL) {
return 0;
}
- if (rte_ring_count(sock->recv_wait_free)) {
- free_ring_pbuf(sock->recv_wait_free);
+ if (gazelle_ring_readover_count(sock->recv_ring) >= SOCK_RECV_FREE_THRES) {
+ free_recv_ring_readover(sock->recv_ring);
+ }
+
+ uint32_t free_count = gazelle_ring_free_count(sock->recv_ring);
+ if (free_count == 0) {
+ GAZELLE_RETURN(EAGAIN);
}
- uint32_t free_count = rte_ring_free_count(sock->recv_ring);
uint32_t data_count = rte_ring_count(sock->conn->recvmbox->ring);
- uint32_t read_max = LWIP_MIN(free_count, data_count);
- struct pbuf *pbuf = NULL;
+ uint32_t read_num = LWIP_MIN(free_count, data_count);
+ read_num = LWIP_MIN(read_num, SOCK_RECV_RING_SIZE);
+ struct pbuf *pbufs[SOCK_RECV_RING_SIZE];
uint32_t read_count = 0;
ssize_t recv_len = 0;
- int32_t ret;
- for (uint32_t i = 0; i < read_max; i++) {
- err_t err = netconn_recv_tcp_pbuf_flags(sock->conn, &pbuf, apiflags);
+ for (uint32_t i = 0; i < read_num; i++) {
+ err_t err = netconn_recv_tcp_pbuf_flags(sock->conn, &pbufs[i], apiflags);
if (err != ERR_OK) {
if (recv_len > 0) {
/* already received data, return that (this trusts in getting the same error from
@@ -448,35 +413,28 @@ ssize_t read_lwip_data(struct lwip_sock *sock, int32_t flags, u8_t apiflags)
return (err == ERR_CLSD) ? 0 : -1;
}
- if (!(flags & MSG_PEEK)) {
- ret = rte_ring_sp_enqueue(sock->recv_ring, pbuf);
- if (ret != 0) {
- pbuf_free(pbuf);
- sock->stack->stats.read_lwip_drop++;
- break;
- }
- read_count++;
- }
-
- if (get_protocol_stack_group()->latency_start) {
- calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_LWIP);
- }
-
- recv_len += pbuf->len;
+ recv_len += pbufs[i]->tot_len;
+ read_count++;
/* once we have some data to return, only add more if we don't need to wait */
apiflags |= NETCONN_DONTBLOCK | NETCONN_NOFIN;
}
- if (data_count > read_count) {
- add_recv_list(sock->conn->socket);
+ if (!(flags & MSG_PEEK)) {
+ uint32_t enqueue_num = gazelle_ring_sp_enqueue(sock->recv_ring, (void **)pbufs, read_count);
+ for (uint32_t i = enqueue_num; i < read_count; i++) {
+ /* update receive window */
+ tcp_recved(sock->conn->pcb.tcp, pbufs[i]->tot_len);
+ pbuf_free(pbufs[i]);
+ sock->stack->stats.read_lwip_drop++;
+ }
}
- if (recv_len > 0 && (flags & MSG_PEEK) == 0) {
- add_epoll_event(sock->conn, EPOLLIN);
+ for (uint32_t i = 0; get_protocol_stack_group()->latency_start && i < read_count; i++) {
+ calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_LWIP);
}
- sock->stack->stats.read_lwip_cnt += read_count;
+ sock->stack->stats.read_lwip_cnt += read_count;
if (recv_len == 0) {
GAZELLE_RETURN(EAGAIN);
}
@@ -532,14 +490,12 @@ ssize_t gazelle_send(int32_t fd, const void *buf, size_t len, int32_t flags)
GAZELLE_RETURN(EINVAL);
}
- sock->send_flags = flags;
ssize_t send = write_stack_data(sock, buf, len);
if (send < 0) {
GAZELLE_RETURN(EAGAIN);
} else if (send == 0) {
return 0;
}
- rte_smp_mb();
rpc_call_send(fd, NULL, send, flags);
return send;
@@ -574,22 +530,52 @@ ssize_t sendmsg_to_stack(int32_t s, const struct msghdr *message, int32_t flags)
return buflen;
}
+static inline void del_data_in_event(struct lwip_sock *sock)
+{
+ pthread_spin_lock(&sock->wakeup->event_list_lock);
+
+ /* check again avoid cover event add in stack thread */
+ if (!NETCONN_IS_DATAIN(sock)) {
+ sock->events &= ~EPOLLIN;
+
+ if (sock->events == 0) {
+ list_del_node_null(&sock->event_list);
+ }
+ }
+
+ pthread_spin_unlock(&sock->wakeup->event_list_lock);
+}
+
+static struct pbuf *pbuf_free_partial(struct pbuf *pbuf, uint16_t free_len)
+{
+ while (free_len && pbuf) {
+ if (free_len >= pbuf->len) {
+ struct pbuf *p = pbuf;
+ pbuf = pbuf->next;
+ free_len = free_len - p->len;
+ } else {
+ pbuf_remove_header(pbuf, free_len);
+ break;
+ }
+ }
+
+ return pbuf;
+}
+
ssize_t read_stack_data(int32_t fd, void *buf, size_t len, int32_t flags)
{
size_t recv_left = len;
struct pbuf *pbuf = NULL;
ssize_t recvd = 0;
- int32_t ret;
- u16_t copy_len;
+ uint16_t copy_len;
struct lwip_sock *sock = get_socket(fd);
if (sock == NULL) {
LSTACK_LOG(ERR, LSTACK, "get_socket null fd %d.\n", fd);
GAZELLE_RETURN(EINVAL);
}
- sock->recv_flags = flags;
- if ((sock->events & EPOLLERR) && !NETCONN_IS_DATAIN(sock)) {
+ if (sock->errevent > 0) {
return 0;
}
@@ -598,35 +584,39 @@ ssize_t read_stack_data(int32_t fd, void *buf, size_t len, int32_t flags)
pbuf = sock->recv_lastdata;
sock->recv_lastdata = NULL;
} else {
- ret = rte_ring_sc_dequeue(sock->recv_ring, (void **)&pbuf);
- if (ret != 0) {
+ if (gazelle_ring_read(sock->recv_ring, (void **)&pbuf, 1) != 1) {
break;
}
}
- copy_len = (recv_left > pbuf->tot_len) ? pbuf->tot_len : (u16_t)recv_left;
+ copy_len = (recv_left > pbuf->len) ? pbuf->len : (uint16_t)recv_left;
pbuf_copy_partial(pbuf, (char *)buf + recvd, copy_len, 0);
recvd += copy_len;
recv_left -= copy_len;
- if (pbuf->tot_len > copy_len) {
- sock->recv_lastdata = pbuf_free_header(pbuf, copy_len);
+ if (pbuf->len > copy_len || pbuf->next) {
+ sock->recv_lastdata = pbuf_free_partial(pbuf, copy_len);
} else {
+ if (sock->wakeup) {
+ sock->wakeup->stat.app_read_cnt += 1;
+ }
if (get_protocol_stack_group()->latency_start) {
calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ);
}
- ret = rte_ring_sp_enqueue(sock->recv_wait_free, pbuf);
- if (ret != 0) {
- pbuf_free(pbuf);
- }
- sock->recv_lastdata = NULL;
- __sync_fetch_and_add(&sock->stack->stats.app_read_cnt, 1);
+ gazelle_ring_read_over(sock->recv_ring);
}
}
+ /* rte_ring_count reduce lock */
+ if (sock->wakeup && sock->wakeup->type == WAKEUP_EPOLL && (sock->events & EPOLLIN)) {
+ del_data_in_event(sock);
+ }
+
if (recvd == 0) {
- sock->stack->stats.read_null++;
+ if (sock->wakeup) {
+ sock->wakeup->stat.read_null++;
+ }
GAZELLE_RETURN(EAGAIN);
}
return recvd;
@@ -634,9 +624,9 @@ ssize_t read_stack_data(int32_t fd, void *buf, size_t len, int32_t flags)
void add_recv_list(int32_t fd)
{
- struct lwip_sock *sock = get_socket(fd);
+ struct lwip_sock *sock = get_socket_by_fd(fd);
- if (sock->stack && list_is_empty(&sock->recv_list)) {
+ if (sock && sock->stack && list_is_null(&sock->recv_list)) {
list_add_node(&sock->stack->recv_list, &sock->recv_list);
}
}
@@ -648,24 +638,26 @@ void read_recv_list(struct protocol_stack *stack, uint32_t max_num)
struct lwip_sock *sock;
uint32_t read_num = 0;
+ struct list_node *last_node = list->prev;
list_for_each_safe(node, temp, list) {
sock = container_of(node, struct lwip_sock, recv_list);
- if (sock->conn == NULL || sock->recv_ring == NULL || sock->send_ring == NULL || sock->conn->pcb.tcp == NULL) {
- list_del_node_init(&sock->recv_list);
+ if (sock->conn == NULL || sock->conn->recvmbox == NULL || rte_ring_count(sock->conn->recvmbox->ring) == 0) {
+ list_del_node_null(&sock->recv_list);
continue;
}
- if (rte_ring_free_count(sock->recv_ring)) {
- list_del_node_init(&sock->recv_list);
- ssize_t len = lwip_recv(sock->conn->socket, NULL, 0, sock->recv_flags);
- if (len == 0) {
- /* FIXME: should use POLLRDHUP, when connection be closed. lwip event-callback no POLLRDHUP */
- add_epoll_event(sock->conn, EPOLLERR);
- }
+ ssize_t len = lwip_recv(sock->conn->socket, NULL, 0, 0);
+ if (len == 0) {
+ /* FIXME: should use POLLRDHUP, when connection be closed. lwip event-callback no POLLRDHUP */
+ sock->errevent = 1;
+ add_epoll_event(sock->conn, EPOLLERR);
+ } else if (len > 0) {
+ add_epoll_event(sock->conn, EPOLLIN);
}
- if (++read_num >= max_num) {
+ /* last_node:recv only once per sock. max_num avoid cost too much time this loop */
+ if (++read_num >= max_num || last_node == node) {
break;
}
}
@@ -684,14 +676,14 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s
if (netconn != NULL && netconn->recvmbox != NULL) {
conn->recv_cnt = rte_ring_count(netconn->recvmbox->ring);
+ conn->fd = netconn->socket;
struct lwip_sock *sock = get_socket(netconn->socket);
if (netconn->socket > 0 && sock != NULL && sock->recv_ring != NULL && sock->send_ring != NULL) {
- conn->recv_ring_cnt = rte_ring_count(sock->recv_ring);
+ conn->recv_ring_cnt = gazelle_ring_readable_count(sock->recv_ring);
conn->recv_ring_cnt += (sock->recv_lastdata) ? 1 : 0;
- conn->send_ring_cnt = rte_ring_count(sock->send_ring);
- conn->send_ring_cnt += (sock->send_lastdata) ? 1 : 0;
+ conn->send_ring_cnt = gazelle_ring_readover_count(sock->send_ring);
if (sock->wakeup) {
sem_getvalue(&sock->wakeup->event_sem, &conn->sem_cnt);
@@ -756,9 +748,11 @@ void create_shadow_fd(struct rpc_msg *msg)
}
clone_lwip_socket_opt(clone_sock, sock);
- clone_sock->shadowed_sock = sock;
- listen_list_add_node(fd, clone_fd);
+ while (sock->listen_next) {
+ sock = sock->listen_next;
+ }
+ sock->listen_next = clone_sock;
int32_t ret = lwip_bind(clone_fd, addr, addr_len);
if (ret < 0) {
@@ -843,11 +837,6 @@ static uint32_t get_list_count(struct list_node *list)
return count;
}
-void stack_eventlist_count(struct rpc_msg *msg)
-{
- msg->result = get_list_count(&get_protocol_stack()->event_list);
-}
-
void stack_sendlist_count(struct rpc_msg *msg)
{
msg->result = get_list_count(&get_protocol_stack()->send_list);
diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c
index 88513ba..a1f3790 100644
--- a/src/lstack/core/lstack_protocol_stack.c
+++ b/src/lstack/core/lstack_protocol_stack.c
@@ -11,6 +11,7 @@
*/
#define _GNU_SOURCE
#include <pthread.h>
+#include <stdatomic.h>
#include <lwip/sockets.h>
#include <lwip/tcpip.h>
@@ -30,6 +31,7 @@
#include "lstack_protocol_stack.h"
#include "lstack_cfg.h"
#include "lstack_control_plane.h"
+#include "posix/lstack_epoll.h"
#include "lstack_stack_stat.h"
#define READ_LIST_MAX 32
@@ -39,7 +41,6 @@
static PER_THREAD uint16_t g_stack_idx = PROTOCOL_STACK_MAX;
static struct protocol_stack_group g_stack_group = {0};
-static PER_THREAD long g_stack_tid = 0;
void set_init_fail(void);
typedef void *(*stack_thread_func)(void *arg);
@@ -66,6 +67,8 @@ static inline void set_stack_idx(uint16_t idx)
long get_stack_tid(void)
{
+ static PER_THREAD long g_stack_tid = 0;
+
if (g_stack_tid == 0) {
g_stack_tid = syscall(__NR_gettid);
}
@@ -96,17 +99,37 @@ struct protocol_stack *get_protocol_stack_by_fd(int32_t fd)
return sock->stack;
}
-struct protocol_stack *get_minconn_protocol_stack(void)
+struct protocol_stack *get_bind_protocol_stack(void)
{
- int32_t min_index = 0;
+ static PER_THREAD struct protocol_stack *bind_stack = NULL;
+
+ /* same app communication thread bind same stack */
+ if (bind_stack) {
+ return bind_stack;
+ }
- for (int32_t i = 1; i < g_stack_group.stack_num; i++) {
- if (g_stack_group.stacks[i]->conn_num < g_stack_group.stacks[min_index]->conn_num) {
- min_index = i;
+ struct protocol_stack_group *stack_group = get_protocol_stack_group();
+ uint16_t index = 0;
+
+ /* close listen shadow, per app communication thread select only one stack */
+ if (get_global_cfg_params()->listen_shadow == false) {
+ static uint16_t stack_index = 0;
+ index = atomic_fetch_add(&stack_index, 1);
+ if (index >= stack_group->stack_num) {
+ LSTACK_LOG(ERR, LSTACK, "thread =%hu larger than stack num = %hu\n", index, stack_group->stack_num);
+ return NULL;
+ }
+ /* use listen shadow, app communication thread maybe more than stack num, select the least load stack */
+ } else {
+ for (uint16_t i = 1; i < stack_group->stack_num; i++) {
+ if (stack_group->stacks[i]->conn_num < stack_group->stacks[index]->conn_num) {
+ index = i;
+ }
}
}
- return g_stack_group.stacks[min_index];
+ bind_stack = stack_group->stacks[index];
+ return stack_group->stacks[index];
}
void lstack_low_power_idling(void)
@@ -193,7 +216,7 @@ static int32_t create_thread(uint16_t queue_id, char *thread_name, stack_thread_
return 0;
}
-static void* gazelle_weakup_thread(void *arg)
+static void* gazelle_wakeup_thread(void *arg)
{
uint16_t queue_id = *(uint16_t *)arg;
struct protocol_stack *stack = get_protocol_stack_group()->stacks[queue_id];
@@ -203,17 +226,13 @@ static void* gazelle_weakup_thread(void *arg)
LSTACK_LOG(INFO, LSTACK, "weakup_%02d start\n", stack->queue_id);
+ sem_t *event_sem[WAKEUP_MAX_NUM];
+ int num;
for (;;) {
- if (rte_ring_count(stack->wakeup_ring) == 0) {
- continue;
- }
-
- sem_t *event_sem;
- if (rte_ring_sc_dequeue(stack->wakeup_ring, (void **)&event_sem)) {
- continue;
+ num = gazelle_light_ring_dequeue_burst(stack->wakeup_ring, (void **)event_sem, WAKEUP_MAX_NUM);
+ for (int i = 0; i < num; i++) {
+ sem_post(event_sem[i]);
}
-
- sem_post(event_sem);
}
return NULL;
@@ -233,12 +252,8 @@ static int32_t init_stack_value(struct protocol_stack *stack, uint16_t queue_id)
stack->lwip_stats = &lwip_stats;
init_list_node(&stack->recv_list);
- init_list_node(&stack->listen_list);
- init_list_node(&stack->event_list);
init_list_node(&stack->send_list);
- pthread_spin_init(&stack->event_lock, PTHREAD_PROCESS_SHARED);
-
sys_calibrate_tsc();
stack_stat_init();
@@ -297,8 +312,10 @@ static void* gazelle_kernel_event(void *arg)
}
for (int32_t i = 0; i < event_num; i++) {
- if (events[i].data.ptr) {
- sem_post((sem_t *)events[i].data.ptr);
+ struct wakeup_poll *wakeup = events[i].data.ptr;
+ if (wakeup) {
+ __atomic_store_n(&wakeup->have_kernel_event, true, __ATOMIC_RELEASE);
+ sem_post(&wakeup->event_sem);
}
}
}
@@ -311,7 +328,7 @@ static int32_t create_companion_thread(struct protocol_stack_group *stack_group,
int32_t ret;
if (stack_group->wakeup_enable) {
- ret = create_thread(stack->queue_id, "gazelleweakup", gazelle_weakup_thread);
+ ret = create_thread(stack->queue_id, "gazelleweakup", gazelle_wakeup_thread);
if (ret != 0) {
LSTACK_LOG(ERR, LSTACK, "gazelleweakup ret=%d errno=%d\n", ret, errno);
return ret;
@@ -339,13 +356,11 @@ static struct protocol_stack * stack_thread_init(uint16_t queue_id)
struct protocol_stack *stack = malloc(sizeof(*stack));
if (stack == NULL) {
- sem_post(&stack_group->thread_phase1);
LSTACK_LOG(ERR, LSTACK, "malloc stack failed\n");
return NULL;
}
if (init_stack_value(stack, queue_id) != 0) {
- sem_post(&stack_group->thread_phase1);
free(stack);
return NULL;
}
@@ -358,7 +373,6 @@ static struct protocol_stack * stack_thread_init(uint16_t queue_id)
if (use_ltran()) {
if (client_reg_thrd_ring() != 0) {
- sem_post(&stack_group->thread_phase1);
free(stack);
return NULL;
}
@@ -419,6 +433,8 @@ static int32_t init_protocol_sem(void)
int32_t ret;
struct protocol_stack_group *stack_group = get_protocol_stack_group();
+ pthread_spin_init(&stack_group->wakeup_list_lock, PTHREAD_PROCESS_PRIVATE);
+
if (!use_ltran()) {
ret = sem_init(&stack_group->ethdev_init, 0, 0);
if (ret < 0) {
@@ -449,6 +465,7 @@ int32_t init_protocol_stack(void)
stack_group->stack_num = get_global_cfg_params()->num_cpu;
stack_group->wakeup_enable = (get_global_cfg_params()->num_wakeup > 0) ? true : false;
+ stack_group->wakeup_list = NULL;
if (init_protocol_sem() != 0) {
return -1;
@@ -486,58 +503,10 @@ void stack_socket(struct rpc_msg *msg)
}
}
-static inline bool is_real_close(int32_t fd)
-{
- struct lwip_sock *sock = get_socket_by_fd(fd);
-
- /* last sock */
- if (list_is_empty(&sock->attach_list)) {
- return true;
- }
-
- /* listen sock, but have attach sock */
- if (sock->attach_fd == fd) {
- sock->wait_close = true;
- return false;
- } else { /* attach sock */
- /* listen sock is normal */
- struct lwip_sock *listen_sock = get_socket_by_fd(sock->attach_fd);
- if (listen_sock == NULL || !listen_sock->wait_close) {
- list_del_node_init(&sock->attach_list);
- return true;
- }
-
- /* listen sock is wait clsoe. check this is last attach sock */
- struct list_node *list = &(sock->attach_list);
- struct list_node *node, *temp;
- uint32_t list_count = 0;
- list_for_each_safe(node, temp, list) {
- list_count++;
- }
- /* 2:listen sock is wait close and closing attach sock. close listen sock here */
- if (list_count == 2) {
- lwip_close(listen_sock->attach_fd);
- gazelle_clean_sock(listen_sock->attach_fd);
- posix_api->close_fn(listen_sock->attach_fd);
- list_del_node_init(&listen_sock->attach_list);
- }
- list_del_node_init(&sock->attach_list);
- return true;
- }
-
- list_del_node_init(&sock->attach_list);
- return true;
-}
-
void stack_close(struct rpc_msg *msg)
{
int32_t fd = msg->args[MSG_ARG_0].i;
- if (!is_real_close(fd)) {
- msg->result = 0;
- return;
- }
-
msg->result = lwip_close(fd);
if (msg->result != 0) {
LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result);
@@ -556,26 +525,8 @@ void stack_bind(struct rpc_msg *msg)
}
}
-static inline struct lwip_sock *reuse_listen(struct protocol_stack *stack, struct lwip_sock *listen_sock)
-{
- struct list_node *node, *temp;
- struct list_node *list = &(stack->listen_list);
- struct lwip_sock *sock;
-
- list_for_each_safe(node, temp, list) {
- sock = container_of(node, struct lwip_sock, listen_list);
- if (sock->conn->pcb.tcp->local_port == listen_sock->conn->pcb.tcp->local_port &&
- sock->conn->pcb.tcp->local_ip.addr == listen_sock->conn->pcb.tcp->local_ip.addr) {
- return sock;
- }
- }
-
- return NULL;
-}
-
void stack_listen(struct rpc_msg *msg)
{
- struct protocol_stack *stack = get_protocol_stack();
int32_t fd = msg->args[MSG_ARG_0].i;
int32_t backlog = msg->args[MSG_ARG_1].i;
@@ -585,25 +536,9 @@ void stack_listen(struct rpc_msg *msg)
return;
}
- /* stack have listen same ip+port, then attach to old listen */
- struct lwip_sock *listen_sock = reuse_listen(stack, sock);
- if (listen_sock) {
- if (list_is_empty(&sock->attach_list)) {
- list_add_node(&listen_sock->attach_list, &sock->attach_list);
- }
- sock->attach_fd = listen_sock->conn->socket;
- msg->result = 0;
- return;
- }
-
/* new listen add to stack listen list */
msg->result = lwip_listen(fd, backlog);
- if (msg->result == 0) {
- if (list_is_empty(&sock->listen_list)) {
- list_add_node(&stack->listen_list, &sock->listen_list);
- }
- sock->attach_fd = fd;
- } else {
+ if (msg->result != 0) {
LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result);
}
}
@@ -611,28 +546,35 @@ void stack_listen(struct rpc_msg *msg)
void stack_accept(struct rpc_msg *msg)
{
int32_t fd = msg->args[MSG_ARG_0].i;
+ msg->result = -1;
int32_t accept_fd = lwip_accept(fd, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p);
- if (accept_fd > 0) {
- struct lwip_sock *sock = get_socket(accept_fd);
- if (sock && sock->stack) {
- msg->result = accept_fd;
- return;
- }
+ if (accept_fd < 0) {
+ LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd);
+ return;
+ }
+ struct lwip_sock *sock = get_socket(accept_fd);
+ if (sock == NULL || sock->stack == NULL) {
lwip_close(accept_fd);
gazelle_clean_sock(accept_fd);
posix_api->close_fn(accept_fd);
+ LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd);
+ return;
}
- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d attach_fd %d failed %d\n", get_stack_tid(), msg->args[MSG_ARG_0].i,
- fd, accept_fd);
- msg->result = -1;
+ msg->result = accept_fd;
+ if (rte_ring_count(sock->conn->recvmbox->ring)) {
+ add_recv_list(accept_fd);
+ }
}
void stack_connect(struct rpc_msg *msg)
{
msg->result = lwip_connect(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].socklen);
+ if (msg->result < 0) {
+ msg->result = -errno;
+ }
}
void stack_getpeername(struct rpc_msg *msg)
@@ -723,6 +665,7 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack
ret = gazelle_alloc_pktmbuf(stack->rx_pktmbuf_pool, &mbuf_copy, 1);
if (ret != 0) {
+ stack->stats.rx_allocmbuf_fail++;
return;
}
copy_mbuf(mbuf_copy, mbuf);
@@ -737,22 +680,28 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack
/* when fd is listenfd, listenfd of all protocol stack thread will be closed */
int32_t stack_broadcast_close(int32_t fd)
{
- struct lwip_sock *sock = NULL;
- int32_t next_fd;
+ struct lwip_sock *sock = get_socket(fd);
+ int32_t ret = 0;
+
+ do {
+ sock = sock->listen_next;
+ if (rpc_call_close(fd)) {
+ ret = -1;
+ }
- while (fd > 0) {
- sock = get_socket(fd);
if (sock == NULL) {
- LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null\n", get_stack_tid(), fd);
- GAZELLE_RETURN(EINVAL);
+ break;
}
- next_fd = sock->nextfd;
+ fd = sock->conn->socket;
+ } while (sock);
- rpc_call_close(fd);
- fd = next_fd;
- }
+ return ret;
+}
- return 0;
+/* choice one stack listen */
+int32_t stack_single_listen(int32_t fd, int32_t backlog)
+{
+ return rpc_call_listen(fd, backlog);
}
/* listen sync to all protocol stack thread, so that any protocol stack thread can build connect */
@@ -797,44 +746,59 @@ int32_t stack_broadcast_listen(int32_t fd, int32_t backlog)
return 0;
}
-/* ergodic the protocol stack thread to find the connection, because all threads are listening */
-int32_t stack_broadcast_accept(int32_t fd, struct sockaddr *addr, socklen_t *addrlen)
+static struct lwip_sock *get_min_accept_sock(int32_t fd)
{
struct lwip_sock *sock = get_socket(fd);
- if (sock == NULL || sock->attach_fd < 0) {
- errno = EINVAL;
- return -1;
- }
- fd = sock->attach_fd;
-
struct lwip_sock *min_sock = NULL;
- int32_t min_fd = fd;
- while (fd > 0) {
- sock = get_socket(fd);
- if (sock == NULL) {
- GAZELLE_RETURN(EINVAL);
- }
- struct lwip_sock *attach_sock = get_socket(sock->attach_fd);
- if (attach_sock == NULL) {
- GAZELLE_RETURN(EINVAL);
- }
- if (!NETCONN_IS_ACCEPTIN(attach_sock)) {
- fd = sock->nextfd;
+ while (sock) {
+ if (!NETCONN_IS_ACCEPTIN(sock)) {
+ sock = sock->listen_next;
continue;
}
- if (min_sock == NULL || min_sock->stack->conn_num > attach_sock->stack->conn_num) {
- min_sock = attach_sock;
- min_fd = sock->attach_fd;
+ if (min_sock == NULL || min_sock->stack->conn_num > sock->stack->conn_num) {
+ min_sock = sock;
}
- fd = sock->nextfd;
+ sock = sock->listen_next;
+ }
+
+ return min_sock;
+}
+
+static void inline del_accept_in_event(struct lwip_sock *sock)
+{
+ pthread_spin_lock(&sock->wakeup->event_list_lock);
+
+ if (!NETCONN_IS_ACCEPTIN(sock)) {
+ sock->events &= ~EPOLLIN;
+ if (sock->events == 0) {
+ list_del_node_null(&sock->event_list);
+ }
}
+ pthread_spin_unlock(&sock->wakeup->event_list_lock);
+}
+
+/* ergodic the protocol stack thread to find the connection, because all threads are listening */
+int32_t stack_broadcast_accept(int32_t fd, struct sockaddr *addr, socklen_t *addrlen)
+{
int32_t ret = -1;
- if (min_sock) {
- ret = rpc_call_accept(min_fd, addr, addrlen);
+
+ struct lwip_sock *sock = get_socket(fd);
+ if (sock == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ struct lwip_sock *min_sock = get_min_accept_sock(fd);
+ if (min_sock && min_sock->conn) {
+ ret = rpc_call_accept(min_sock->conn->socket, addr, addrlen);
+ }
+
+ if (min_sock && min_sock->wakeup && min_sock->wakeup->type == WAKEUP_EPOLL) {
+ del_accept_in_event(min_sock);
}
if (ret < 0) {
diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c
index 743857f..06fac5c 100644
--- a/src/lstack/core/lstack_stack_stat.c
+++ b/src/lstack/core/lstack_stack_stat.c
@@ -25,6 +25,7 @@
#include "gazelle_dfx_msg.h"
#include "lstack_thread_rpc.h"
#include "lstack_stack_stat.h"
+#include "posix/lstack_epoll.h"
#define US_PER_SEC 1000000
@@ -87,6 +88,68 @@ static void set_latency_start_flag(bool start)
}
}
+void register_wakeup(struct wakeup_poll *wakeup)
+{
+ struct protocol_stack_group *stack_group = get_protocol_stack_group();
+
+ pthread_spin_lock(&stack_group->wakeup_list_lock);
+
+ wakeup->next = stack_group->wakeup_list;
+ stack_group->wakeup_list = wakeup;
+
+ pthread_spin_unlock(&stack_group->wakeup_list_lock);
+}
+
+void unregister_wakeup(struct wakeup_poll *wakeup)
+{
+ struct protocol_stack_group *stack_group = get_protocol_stack_group();
+
+ pthread_spin_lock(&stack_group->wakeup_list_lock);
+
+ struct wakeup_poll *node = stack_group->wakeup_list;
+ struct wakeup_poll *pre = NULL;
+
+ while(node && node != wakeup) {
+ pre = node;
+ node = node->next;
+ }
+
+ if (node == NULL) {
+ pthread_spin_unlock(&stack_group->wakeup_list_lock);
+ return;
+ }
+
+ if (pre) {
+ pre->next = node->next;
+ } else {
+ stack_group->wakeup_list = node->next;
+ }
+
+ pthread_spin_unlock(&stack_group->wakeup_list_lock);
+}
+
+static void get_wakeup_stat(struct protocol_stack *stack, struct gazelle_wakeup_stat *stat)
+{
+ struct protocol_stack_group *stack_group = get_protocol_stack_group();
+
+ pthread_spin_lock(&stack_group->wakeup_list_lock);
+
+ struct wakeup_poll *node = stack_group->wakeup_list;
+ while (node) {
+ if (node->bind_stack == stack) {
+ stat->app_events += node->stat.app_events;
+ stat->read_null += node->stat.read_null;
+ stat->app_write_cnt += node->stat.app_write_cnt;
+ stat->app_write_idlefail += node->stat.app_write_idlefail;
+ stat->app_read_cnt += node->stat.app_read_cnt;
+ }
+
+ node = node->next;
+ }
+
+ pthread_spin_unlock(&stack_group->wakeup_list_lock);
+}
+
void lstack_get_low_power_info(struct gazelle_stat_low_power_info *low_power_info)
{
struct cfg_params *cfg = get_global_cfg_params();
@@ -102,21 +165,24 @@ static void get_stack_stats(struct gazelle_stack_dfx_data *dfx, struct protocol_
struct protocol_stack_group *stack_group = get_protocol_stack_group();
dfx->loglevel = rte_log_get_level(RTE_LOGTYPE_LSTACK);
+
lstack_get_low_power_info(&dfx->low_power_info);
- memcpy_s(&dfx->data.pkts, sizeof(dfx->data.pkts), &stack->stats, sizeof(dfx->data.pkts));
+
+ memcpy_s(&dfx->data.pkts.stack_stat, sizeof(struct gazelle_stack_stat), &stack->stats,
+ sizeof(struct gazelle_stack_stat));
+
+ get_wakeup_stat(stack, &dfx->data.pkts.wakeup_stat);
+
dfx->data.pkts.call_alloc_fail = stack_group->call_alloc_fail;
int32_t rpc_call_result = rpc_call_msgcnt(stack);
dfx->data.pkts.call_msg_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result;
rpc_call_result = rpc_call_recvlistcnt(stack);
- dfx->data.pkts.recv_list = (rpc_call_result < 0) ? 0 : rpc_call_result;
-
- rpc_call_result = rpc_call_eventlistcnt(stack);
- dfx->data.pkts.event_list = (rpc_call_result < 0) ? 0 : rpc_call_result;
+ dfx->data.pkts.recv_list_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result;
rpc_call_result = rpc_call_sendlistcnt(stack);
- dfx->data.pkts.send_list = (rpc_call_result < 0) ? 0 : rpc_call_result;
+ dfx->data.pkts.send_list_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result;
dfx->data.pkts.conn_num = stack->conn_num;
}
@@ -182,6 +248,8 @@ int32_t handle_stack_cmd(int32_t fd, enum GAZELLE_STAT_MODE stat_mode)
for (uint32_t i = 0; i < stack_group->stack_num; i++) {
struct protocol_stack *stack = stack_group->stacks[i];
+
+ memset_s(&dfx, sizeof(dfx), 0, sizeof(dfx));
get_stack_dfx_data(&dfx, stack, stat_mode);
if (!use_ltran() &&
diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c
index 312e192..8937920 100644
--- a/src/lstack/core/lstack_thread_rpc.c
+++ b/src/lstack/core/lstack_thread_rpc.c
@@ -23,34 +23,53 @@
#include "lstack_dpdk.h"
#include "lstack_thread_rpc.h"
-static PER_THREAD struct rte_mempool *rpc_pool = NULL;
+#define RPC_MSG_MAX 32
+struct rpc_msg_pool {
+ struct rpc_msg msgs[RPC_MSG_MAX];
+ uint32_t prod __rte_cache_aligned;
+ uint32_t cons __rte_cache_aligned;
+};
+
+static PER_THREAD struct rpc_msg_pool *g_rpc_pool = NULL;
+
+static inline __attribute__((always_inline)) struct rpc_msg *get_rpc_msg(struct rpc_msg_pool *rpc_pool)
+{
+ uint32_t cons = __atomic_load_n(&rpc_pool->cons, __ATOMIC_ACQUIRE);
+ uint32_t prod = rpc_pool->prod + 1;
+
+ if (prod == cons) {
+ return NULL;
+ }
+
+ rpc_pool->prod = prod;
+ return &rpc_pool->msgs[prod];
+}
static inline __attribute__((always_inline))
struct rpc_msg *rpc_msg_alloc(struct protocol_stack *stack, rpc_msg_func func)
{
- int32_t ret;
struct rpc_msg *msg = NULL;
if (stack == NULL) {
return NULL;
}
- static uint16_t pool_index = 0;
- if (rpc_pool == NULL) {
- rpc_pool = create_rpc_mempool("rpc_msg", atomic_fetch_add(&pool_index, 1));
- if (rpc_pool == NULL) {
+ if (g_rpc_pool == NULL) {
+ g_rpc_pool = calloc(1, sizeof(struct rpc_msg_pool));
+ if (g_rpc_pool == NULL) {
+ get_protocol_stack_group()->call_alloc_fail++;
return NULL;
}
}
- ret = rte_mempool_get(rpc_pool, (void **)&msg);
- if (ret < 0) {
+ msg = get_rpc_msg(g_rpc_pool);
+ if (msg == NULL) {
get_protocol_stack_group()->call_alloc_fail++;
return NULL;
}
- msg->pool = rpc_pool;
+ msg->pool = g_rpc_pool;
- pthread_spin_init(&msg->lock, PTHREAD_PROCESS_SHARED);
+ pthread_spin_init(&msg->lock, PTHREAD_PROCESS_PRIVATE);
msg->func = func;
msg->self_release = 1;
@@ -64,7 +83,8 @@ void rpc_msg_free(struct rpc_msg *msg)
msg->self_release = 0;
msg->func = NULL;
- rte_mempool_put(msg->pool, (void *)msg);
+
+ atomic_fetch_add(&msg->pool->cons, 1);
}
static inline __attribute__((always_inline))
@@ -109,8 +129,6 @@ void poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num)
stack->stats.call_null++;
}
- rte_mb();
-
if (msg->self_release) {
pthread_spin_unlock(&msg->lock);
} else {
@@ -192,16 +210,6 @@ int32_t rpc_call_thread_regphase2(struct protocol_stack *stack, void *conn)
return rpc_sync_call(&stack->rpc_queue, msg);
}
-int32_t rpc_call_eventlistcnt(struct protocol_stack *stack)
-{
- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_eventlist_count);
- if (msg == NULL) {
- return -1;
- }
-
- return rpc_sync_call(&stack->rpc_queue, msg);
-}
-
int32_t rpc_call_sendlistcnt(struct protocol_stack *stack)
{
struct rpc_msg *msg = rpc_msg_alloc(stack, stack_sendlist_count);
@@ -222,28 +230,6 @@ int32_t rpc_call_recvlistcnt(struct protocol_stack *stack)
return rpc_sync_call(&stack->rpc_queue, msg);
}
-void add_epoll_event(struct netconn *conn, uint32_t event);
-static void rpc_add_event(struct rpc_msg *msg)
-{
- struct lwip_sock *sock = (struct lwip_sock *)msg->args[MSG_ARG_0].p;
- if (sock->conn) {
- add_epoll_event(sock->conn, sock->events);
- }
-}
-
-void rpc_call_addevent(struct protocol_stack *stack, void *sock)
-{
- struct rpc_msg *msg = rpc_msg_alloc(stack, rpc_add_event);
- if (msg == NULL) {
- return;
- }
-
- msg->args[MSG_ARG_0].p = sock;
-
- msg->self_release = 0;
- rpc_call(&stack->rpc_queue, msg);
-}
-
int32_t rpc_call_arp(struct protocol_stack *stack, struct rte_mbuf *mbuf)
{
struct rpc_msg *msg = rpc_msg_alloc(stack, stack_arp);
@@ -260,7 +246,7 @@ int32_t rpc_call_arp(struct protocol_stack *stack, struct rte_mbuf *mbuf)
int32_t rpc_call_socket(int32_t domain, int32_t type, int32_t protocol)
{
- struct protocol_stack *stack = get_minconn_protocol_stack();
+ struct protocol_stack *stack = get_bind_protocol_stack();
struct rpc_msg *msg = rpc_msg_alloc(stack, stack_socket);
if (msg == NULL) {
return -1;
@@ -342,7 +328,12 @@ int32_t rpc_call_connect(int fd, const struct sockaddr *addr, socklen_t addrlen)
msg->args[MSG_ARG_1].cp = addr;
msg->args[MSG_ARG_2].socklen = addrlen;
- return rpc_sync_call(&stack->rpc_queue, msg);
+ int32_t ret = rpc_sync_call(&stack->rpc_queue, msg);
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+ return ret;
}
int32_t rpc_call_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen)
diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h
index 987828d..aeffbb3 100644
--- a/src/lstack/include/lstack_cfg.h
+++ b/src/lstack/include/lstack_cfg.h
@@ -75,6 +75,7 @@ struct cfg_params {
uint32_t lpm_pkts_in_detect;
bool use_ltran; // ture:lstack read from nic false:read form ltran
bool kni_switch;
+ bool listen_shadow; // true:listen in all stack thread. false:listen in one stack thread.
int dpdk_argc;
char **dpdk_argv;
struct secondary_attach_arg sec_attach_arg;
diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h
index bb9be21..6ffcc41 100644
--- a/src/lstack/include/lstack_dpdk.h
+++ b/src/lstack/include/lstack_dpdk.h
@@ -23,7 +23,7 @@
#include "dpdk_common.h"
struct protocol_stack;
-#define RX_NB_MBUF ((5 * (MAX_CLIENTS / 4)) + (VDEV_RX_QUEUE_SZ * DEFAULT_BACKUP_RING_SIZE_FACTOR))
+#define RX_NB_MBUF ((5 * MAX_CLIENTS) + (VDEV_RX_QUEUE_SZ * DEFAULT_BACKUP_RING_SIZE_FACTOR))
#define RX_MBUF_CACHE_SZ (VDEV_RX_QUEUE_SZ)
#define TX_NB_MBUF (128 * DEFAULT_RING_SIZE)
#define TX_MBUF_CACHE_SZ (DEFAULT_RING_SIZE)
@@ -34,13 +34,13 @@ struct protocol_stack;
#define MAX_PACKET_SZ 2048
+#define RING_SIZE(x) ((x) - 1)
#define MBUF_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM)
#define MAX_CORE_NUM 256
#define CALL_MSG_RING_SIZE (unsigned long long)32
#define CALL_CACHE_SZ 0
-#define CALL_POOL_SZ 128
/* Layout:
* | rte_mbuf | pbuf | custom_free_function | payload |
@@ -62,7 +62,6 @@ int32_t dpdk_eal_init(void);
int32_t pktmbuf_pool_init(struct protocol_stack *stack, uint16_t stack_num);
struct rte_ring *create_ring(const char *name, uint32_t count, uint32_t flags, int32_t queue_id);
int32_t create_shared_ring(struct protocol_stack *stack);
-struct rte_mempool *create_rpc_mempool(const char *name, uint16_t queue_id);
void lstack_log_level_init(void);
int dpdk_ethdev_init(void);
int dpdk_ethdev_start(void);
diff --git a/src/lstack/include/lstack_lockless_queue.h b/src/lstack/include/lstack_lockless_queue.h
index c00d3a2..c70b56a 100644
--- a/src/lstack/include/lstack_lockless_queue.h
+++ b/src/lstack/include/lstack_lockless_queue.h
@@ -1,5 +1,13 @@
/*
-* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved.
+* gazelle is licensed under the Mulan PSL v2.
+* You can use this software according to the terms and conditions of the Mulan PSL v2.
+* You may obtain a copy of Mulan PSL v2 at:
+* http://license.coscl.org.cn/MulanPSL2
+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+* PURPOSE.
+* See the Mulan PSL v2 for more details.
*/
#ifndef __GAZELLE_LOCKLESS_QUEUE_H__
diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h
index c73e3a7..ba57541 100644
--- a/src/lstack/include/lstack_lwip.h
+++ b/src/lstack/include/lstack_lwip.h
@@ -14,18 +14,16 @@
#define __GAZELLE_LWIP_H__
#include "lstack_thread_rpc.h"
+#include "dpdk_common.h"
#include "lwipsock.h"
-#define SOCK_RECV_RING_SIZE (128)
-#define SOCK_SEND_RING_SIZE (32)
#define NETCONN_IS_ACCEPTIN(sock) (((sock)->conn->acceptmbox != NULL) && !sys_mbox_empty((sock)->conn->acceptmbox))
-#define NETCONN_IS_DATAIN(sock) ((rte_ring_count((sock)->recv_ring) || (sock)->recv_lastdata))
-#define NETCONN_IS_DATAOUT(sock) ((rte_ring_count((sock)->send_ring) || (sock)->send_lastdata))
-#define NETCONN_IS_OUTIDLE(sock) rte_ring_free_count((sock)->send_ring)
+#define NETCONN_IS_DATAIN(sock) ((gazelle_ring_readable_count((sock)->recv_ring) || (sock)->recv_lastdata))
+#define NETCONN_IS_DATAOUT(sock) gazelle_ring_readover_count((sock)->send_ring)
+#define NETCONN_IS_OUTIDLE(sock) gazelle_ring_readable_count((sock)->send_ring)
void create_shadow_fd(struct rpc_msg *msg);
-void listen_list_add_node(int32_t head_fd, int32_t add_fd);
void gazelle_init_sock(int32_t fd);
int32_t gazelle_socket(int domain, int type, int protocol);
void gazelle_clean_sock(int32_t fd);
@@ -37,7 +35,6 @@ void read_recv_list(struct protocol_stack *stack, uint32_t max_num);
void send_stack_list(struct protocol_stack *stack, uint32_t send_max);
void add_recv_list(int32_t fd);
void stack_sendlist_count(struct rpc_msg *msg);
-void stack_eventlist_count(struct rpc_msg *msg);
void get_lwip_conntable(struct rpc_msg *msg);
void get_lwip_connnum(struct rpc_msg *msg);
void stack_recvlist_count(struct rpc_msg *msg);
diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h
index bc4e4bd..8a6aa9d 100644
--- a/src/lstack/include/lstack_protocol_stack.h
+++ b/src/lstack/include/lstack_protocol_stack.h
@@ -14,48 +14,52 @@
#define __GAZELLE_PROTOCOL_STACK_H__
#include <semaphore.h>
-#include <pthread.h>
#include <lwip/list.h>
#include <lwip/netif.h>
+#include <rte_common.h>
#include "dpdk_common.h"
#include "lstack_thread_rpc.h"
#include "gazelle_dfx_msg.h"
#include "lstack_lockless_queue.h"
+#define SOCK_RECV_RING_SIZE (128)
+#define SOCK_RECV_FREE_THRES (32)
+#define SOCK_SEND_RING_SIZE (32)
+#define SOCK_SEND_REPLENISH_THRES (16)
+#define WAKEUP_MAX_NUM (32)
+
struct protocol_stack {
uint32_t tid;
uint16_t queue_id;
uint16_t port_id;
uint16_t socket_id;
uint16_t cpu_id;
- volatile uint16_t conn_num;
cpu_set_t idle_cpuset; /* idle cpu in numa of stack, app thread bind to it */
+ int32_t epollfd; /* kernel event thread epoll fd */
- lockless_queue rpc_queue;
struct rte_mempool *rx_pktmbuf_pool;
struct rte_mempool *tx_pktmbuf_pool;
struct rte_ring *rx_ring;
struct rte_ring *tx_ring;
struct rte_ring *reg_ring;
struct rte_ring *wakeup_ring;
-
struct reg_ring_msg *reg_buf;
+ volatile uint16_t conn_num __rte_cache_aligned;
+ lockless_queue rpc_queue __rte_cache_aligned;
+ char pad __rte_cache_aligned;
+
struct netif netif;
+ struct eth_dev_ops *dev_ops;
uint32_t rx_ring_used;
uint32_t tx_ring_used;
- struct eth_dev_ops *dev_ops;
struct list_node recv_list;
- struct list_node listen_list;
struct list_node send_list;
- struct list_node event_list;
- pthread_spinlock_t event_lock;
- int32_t epollfd; /* kernel event thread epoll fd */
- struct gazelle_stat_pkts stats;
- struct gazelle_stack_latency latency;
struct stats_ *lwip_stats;
+ struct gazelle_stack_latency latency;
+ struct gazelle_stack_stat stats __rte_cache_aligned;
};
struct eth_params;
@@ -74,12 +78,14 @@ struct protocol_stack_group {
/* dfx stats */
bool latency_start;
uint64_t call_alloc_fail;
+ pthread_spinlock_t wakeup_list_lock;
+ struct wakeup_poll *wakeup_list __rte_cache_aligned;
};
long get_stack_tid(void);
struct protocol_stack *get_protocol_stack(void);
struct protocol_stack *get_protocol_stack_by_fd(int32_t fd);
-struct protocol_stack *get_minconn_protocol_stack(void);
+struct protocol_stack *get_bind_protocol_stack(void);
struct protocol_stack_group *get_protocol_stack_group(void);
int32_t init_protocol_stack(void);
@@ -96,6 +102,7 @@ int32_t stack_broadcast_close(int32_t fd);
/* listen sync to all protocol stack thread, so that any protocol stack thread can build connect */
int32_t stack_broadcast_listen(int32_t fd, int backlog);
+int32_t stack_single_listen(int32_t fd, int32_t backlog);
/* ergodic the protocol stack thread to find the connection, because all threads are listening */
int32_t stack_broadcast_accept(int32_t fd, struct sockaddr *addr, socklen_t *addrlen);
diff --git a/src/lstack/include/lstack_stack_stat.h b/src/lstack/include/lstack_stack_stat.h
index 2c3bf8f..e152fe6 100644
--- a/src/lstack/include/lstack_stack_stat.h
+++ b/src/lstack/include/lstack_stack_stat.h
@@ -24,4 +24,7 @@ void stack_stat_init(void);
int32_t handle_stack_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode);
uint64_t get_current_time(void);
void lstack_get_low_power_info(struct gazelle_stat_low_power_info *low_power_info);
+void register_wakeup(struct wakeup_poll *wakeup);
+void unregister_wakeup(struct wakeup_poll *wakeup);
+
#endif /* GAZELLE_STACK_STAT_H */
diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h
index 61bcd38..35e6b1e 100644
--- a/src/lstack/include/lstack_thread_rpc.h
+++ b/src/lstack/include/lstack_thread_rpc.h
@@ -37,12 +37,13 @@ union rpc_msg_arg {
socklen_t socklen;
size_t size;
};
+struct rpc_msg_pool;
struct rpc_msg {
pthread_spinlock_t lock; /* msg handler unlock notice sender msg process done */
int32_t self_release; /* 0:msg handler release msg 1:msg sender release msg */
int64_t result; /* func return val */
lockless_queue_node queue_node;
- struct rte_mempool *pool;
+ struct rpc_msg_pool *pool;
rpc_msg_func func; /* msg handle func hook */
union rpc_msg_arg args[RPM_MSG_ARG_SIZE]; /* resolve by type */
@@ -50,11 +51,9 @@ struct rpc_msg {
struct protocol_stack;
void poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num);
-void rpc_call_addevent(struct protocol_stack *stack, void *sock);
int32_t rpc_call_msgcnt(struct protocol_stack *stack);
int32_t rpc_call_shadow_fd(struct protocol_stack *stack, int32_t fd, const struct sockaddr *addr, socklen_t addrlen);
int32_t rpc_call_recvlistcnt(struct protocol_stack *stack);
-int32_t rpc_call_eventlistcnt(struct protocol_stack *stack);
int32_t rpc_call_sendlistcnt(struct protocol_stack *stack);
int32_t rpc_call_thread_regphase1(struct protocol_stack *stack, void *conn);
int32_t rpc_call_thread_regphase2(struct protocol_stack *stack, void *conn);
diff --git a/src/lstack/include/posix/lstack_epoll.h b/src/lstack/include/posix/lstack_epoll.h
index a83f41f..e9f9b91 100644
--- a/src/lstack/include/posix/lstack_epoll.h
+++ b/src/lstack/include/posix/lstack_epoll.h
@@ -20,16 +20,27 @@ extern "C" {
#include <poll.h>
#include <stdbool.h>
#include <semaphore.h>
+#include <pthread.h>
+#include <rte_common.h>
#include "lstack_protocol_stack.h"
+enum wakeup_type {
+ WAKEUP_EPOLL = 0,
+ WAKEUP_POLL,
+};
struct wakeup_poll {
+ /* stack thread read frequently */
+ sem_t event_sem __rte_cache_aligned;
+ enum wakeup_type type __rte_cache_aligned;
+ volatile bool have_kernel_event __rte_cache_aligned;
+ struct gazelle_wakeup_stat stat __rte_cache_aligned;
+ char pad __rte_cache_aligned;
+
bool init;
struct protocol_stack *bind_stack;
- sem_t event_sem;
-
- int32_t epollfd;
- bool have_kernel_fd;
+ int32_t epollfd; /* epoll kernel fd, ctl add into gazelle_kernel_event thread */
+ struct wakeup_poll *next;
/* poll */
struct pollfd *last_fds;
@@ -40,7 +51,8 @@ struct wakeup_poll {
/* epoll */
int32_t stack_fd_cnt[PROTOCOL_STACK_MAX];
struct protocol_stack *max_stack;
- struct list_node event_list; /* epoll temp use */
+ struct list_node event_list;
+ pthread_spinlock_t event_list_lock;
};
int32_t lstack_epoll_create(int32_t size);
diff --git a/src/lstack/lstack.conf b/src/lstack/lstack.conf
index 696dfb9..fdca602 100644
--- a/src/lstack/lstack.conf
+++ b/src/lstack/lstack.conf
@@ -16,6 +16,7 @@ kni_switch=0
low_power_mode=0
num_cpus="2"
+num_wakeup="3"
host_addr="192.168.1.10"
mask_addr="255.255.255.0"
diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c
index 382f3bc..7938520 100644
--- a/src/lstack/netif/lstack_ethdev.c
+++ b/src/lstack/netif/lstack_ethdev.c
@@ -39,10 +39,11 @@ void eth_dev_recv(struct rte_mbuf *mbuf)
struct pbuf_custom *pc = NULL;
struct protocol_stack *stack = get_protocol_stack();
struct rte_mbuf *m = mbuf;
- uint16_t len;
+ uint16_t len, pkt_len;
+ pkt_len = (uint16_t)rte_pktmbuf_pkt_len(m);
while (m != NULL) {
- len = (uint16_t)rte_pktmbuf_pkt_len(m);
+ len = (uint16_t)rte_pktmbuf_data_len(m);
payload = rte_pktmbuf_mtod(m, void *);
pc = mbuf_to_pbuf(m);
pc->custom_free_function = gazelle_free_pbuf;
@@ -51,6 +52,7 @@ void eth_dev_recv(struct rte_mbuf *mbuf)
stack->stats.rx_allocmbuf_fail++;
break;
}
+ next->tot_len = pkt_len;
#if CHECKSUM_CHECK_IP_HW || CHECKSUM_CHECK_TCP_HW
next->ol_flags = m->ol_flags;
#endif
@@ -71,7 +73,6 @@ void eth_dev_recv(struct rte_mbuf *mbuf)
if (ret != ERR_OK) {
LSTACK_LOG(ERR, LSTACK, "eth_dev_recv: failed to handle rx pbuf ret=%d\n", ret);
stack->stats.rx_drop++;
- pbuf_free(head);
}
}
}
@@ -181,7 +182,7 @@ int32_t ethdev_init(struct protocol_stack *stack)
if (use_ltran()) {
stack->rx_ring_used = 0;
- int32_t ret = fill_mbuf_to_ring(stack->rx_pktmbuf_pool, stack->rx_ring, VDEV_RX_QUEUE_SZ - 1);
+ int32_t ret = fill_mbuf_to_ring(stack->rx_pktmbuf_pool, stack->rx_ring, RING_SIZE(VDEV_RX_QUEUE_SZ));
if (ret != 0) {
LSTACK_LOG(ERR, LSTACK, "fill mbuf to rx_ring failed ret=%d\n", ret);
return ret;
diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c
index 5a4e86a..287ac8f 100644
--- a/src/lstack/netif/lstack_vdev.c
+++ b/src/lstack/netif/lstack_vdev.c
@@ -42,14 +42,14 @@ static uint32_t ltran_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pk
uint32_t nr_pkts;
struct rte_mbuf *free_buf[DPDK_PKT_BURST_SIZE];
- rcvd_pkts = rte_ring_en_dequeue_burst(stack->rx_ring, (void **)pkts, max_mbuf);
+ rcvd_pkts = gazelle_ring_sc_dequeue(stack->rx_ring, (void **)pkts, max_mbuf);
stack->rx_ring_used += rcvd_pkts;
if (unlikely(stack->rx_ring_used >= USED_RX_PKTS_WATERMARK)) {
- uint32_t free_cnt = LWIP_MIN(stack->rx_ring_used, DPDK_PKT_BURST_SIZE);
+ uint32_t free_cnt = LWIP_MIN(stack->rx_ring_used, RING_SIZE(DPDK_PKT_BURST_SIZE));
int32_t ret = gazelle_alloc_pktmbuf(stack->rx_pktmbuf_pool, (struct rte_mbuf **)free_buf, free_cnt);
if (likely(ret == 0)) {
- nr_pkts = rte_ring_en_enqueue_bulk(stack->rx_ring, (void **)free_buf, free_cnt);
+ nr_pkts = gazelle_ring_sp_enqueue(stack->rx_ring, (void **)free_buf, free_cnt);
stack->rx_ring_used -= nr_pkts;
} else {
stack->stats.rx_allocmbuf_fail++;
@@ -72,14 +72,14 @@ static uint32_t ltran_tx_xmit(struct protocol_stack *stack, struct rte_mbuf **pk
do {
if (unlikely(stack->tx_ring_used >= INUSE_TX_PKTS_WATERMARK)) {
- uint32_t free_pkts = rte_ring_en_dequeue_burst(stack->tx_ring, (void **)free_buf, stack->tx_ring_used);
+ uint32_t free_pkts = gazelle_ring_sc_dequeue(stack->tx_ring, (void **)free_buf, stack->tx_ring_used);
for (uint32_t i = 0; i < free_pkts; i++) {
rte_pktmbuf_free(free_buf[i]);
}
stack->tx_ring_used -= free_pkts;
}
- sent_pkts += rte_ring_en_enqueue_bulk(stack->tx_ring, (void **)(&pkts[sent_pkts]), nr_pkts - sent_pkts);
+ sent_pkts += gazelle_ring_sp_enqueue(stack->tx_ring, (void **)(&pkts[sent_pkts]), nr_pkts - sent_pkts);
} while ((sent_pkts < nr_pkts) && (ENQUEUE_RING_RETRY_TIMEOUT > sys_now() - tbegin) && get_register_state());
stack->tx_ring_used += sent_pkts;
@@ -128,7 +128,7 @@ int32_t vdev_reg_xmit(enum reg_ring_type type, struct gazelle_quintuple *qtuple)
}
do {
- (void)rte_ring_en_dequeue_burst(stack->reg_ring, free_buf, VDEV_REG_QUEUE_SZ);
+ (void)gazelle_ring_sc_dequeue(stack->reg_ring, free_buf, VDEV_REG_QUEUE_SZ);
if (get_reg_ring_free_count(stack->reg_ring) == 0) {
continue;
@@ -144,7 +144,7 @@ int32_t vdev_reg_xmit(enum reg_ring_type type, struct gazelle_quintuple *qtuple)
}
free_buf[0] = tmp_buf;
- sent_pkts = rte_ring_en_enqueue_bulk(stack->reg_ring, free_buf, 1);
+ sent_pkts = gazelle_ring_sp_enqueue(stack->reg_ring, free_buf, 1);
} while ((sent_pkts < 1) && (ENQUEUE_RING_RETRY_TIMEOUT > sys_now() - tbegin) && get_register_state());
if (sent_pkts == 1) {
diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c
index 8d71966..7db1adc 100644
--- a/src/ltran/ltran_dfx.c
+++ b/src/ltran/ltran_dfx.c
@@ -546,32 +546,28 @@ static void gazelle_print_lstack_stat_brief(struct gazelle_stat_lstack_total *st
static void show_lstack_stats(struct gazelle_stack_dfx_data *lstack_stat)
{
printf("\n------ stack tid: %6u ------\n", lstack_stat->tid);
- printf("rx_pkts: %-20"PRIu64" ", lstack_stat->data.pkts.rx);
- printf("rx_drop: %-20"PRIu64" ", lstack_stat->data.pkts.rx_drop);
- printf("rx_allocmbuf_fail: %-10"PRIu64"\n", lstack_stat->data.pkts.rx_allocmbuf_fail);
- printf("tx_pkts: %-20"PRIu64" ", lstack_stat->data.pkts.tx);
- printf("tx_drop: %-20"PRIu64" ", lstack_stat->data.pkts.tx_drop);
- printf("tx_allocmbuf_fail: %-10"PRIu64"\n", lstack_stat->data.pkts.tx_allocmbuf_fail);
- printf("app_read: %-19"PRIu64" ", lstack_stat->data.pkts.app_read_cnt);
- printf("read_lwip: %-18"PRIu64" ", lstack_stat->data.pkts.read_lwip_cnt);
- printf("read_lwip_drop: %-13"PRIu64" \n", lstack_stat->data.pkts.read_lwip_drop);
- printf("app_write: %-18"PRIu64" ", lstack_stat->data.pkts.app_write_cnt);
- printf("write_lwip: %-17"PRIu64" ", lstack_stat->data.pkts.write_lwip_cnt);
- printf("app_get_idlefail: %-11"PRIu64" \n", lstack_stat->data.pkts.app_write_idlefail);
- printf("app_write_drop: %-13"PRIu64" ", lstack_stat->data.pkts.app_write_drop);
- printf("write_lwip_drop: %-12"PRIu64" ", lstack_stat->data.pkts.write_lwip_drop);
- printf("app_write_idlebuf: %-10"PRIu16" \n", lstack_stat->data.pkts.send_idle_ring_cnt);
- printf("event_list: %-17"PRIu64" ", lstack_stat->data.pkts.event_list);
- printf("recv_list: %-18"PRIu64" ", lstack_stat->data.pkts.recv_list);
+ printf("rx_pkts: %-20"PRIu64" ", lstack_stat->data.pkts.stack_stat.rx);
+ printf("rx_drop: %-20"PRIu64" ", lstack_stat->data.pkts.stack_stat.rx_drop);
+ printf("rx_allocmbuf_fail: %-10"PRIu64"\n", lstack_stat->data.pkts.stack_stat.rx_allocmbuf_fail);
+ printf("tx_pkts: %-20"PRIu64" ", lstack_stat->data.pkts.stack_stat.tx);
+ printf("tx_drop: %-20"PRIu64" ", lstack_stat->data.pkts.stack_stat.tx_drop);
+ printf("tx_allocmbuf_fail: %-10"PRIu64"\n", lstack_stat->data.pkts.stack_stat.tx_allocmbuf_fail);
+ printf("app_read: %-19"PRIu64" ", lstack_stat->data.pkts.wakeup_stat.app_read_cnt);
+ printf("read_lwip: %-18"PRIu64" ", lstack_stat->data.pkts.stack_stat.read_lwip_cnt);
+ printf("read_lwip_drop: %-13"PRIu64" \n", lstack_stat->data.pkts.stack_stat.read_lwip_drop);
+ printf("app_write: %-18"PRIu64" ", lstack_stat->data.pkts.wakeup_stat.app_write_cnt);
+ printf("write_lwip: %-17"PRIu64" ", lstack_stat->data.pkts.stack_stat.write_lwip_cnt);
+ printf("app_get_idlefail: %-11"PRIu64" \n", lstack_stat->data.pkts.wakeup_stat.app_write_idlefail);
+ printf("recv_list: %-18"PRIu64" ", lstack_stat->data.pkts.recv_list_cnt);
+ printf("send_list: %-18"PRIu64" ", lstack_stat->data.pkts.send_list_cnt);
printf("conn_num: %-19"PRIu16" \n", lstack_stat->data.pkts.conn_num);
- printf("wakeup_events: %-14"PRIu64" ", lstack_stat->data.pkts.wakeup_events);
- printf("app_events: %-17"PRIu64" ", lstack_stat->data.pkts.app_events);
- printf("read_null: %-18"PRIu64" \n", lstack_stat->data.pkts.read_null);
+ printf("wakeup_events: %-14"PRIu64" ", lstack_stat->data.pkts.stack_stat.wakeup_events);
+ printf("app_events: %-17"PRIu64" ", lstack_stat->data.pkts.wakeup_stat.app_events);
+ printf("read_null: %-18"PRIu64" \n", lstack_stat->data.pkts.wakeup_stat.read_null);
printf("call_msg: %-19"PRIu64" ", lstack_stat->data.pkts.call_msg_cnt);
printf("call_alloc_fail: %-12"PRIu64" ", lstack_stat->data.pkts.call_alloc_fail);
- printf("call_null: %-18"PRIu64" \n", lstack_stat->data.pkts.call_null);
- printf("send_self_rpc: %-14"PRIu64" ", lstack_stat->data.pkts.send_self_rpc);
- printf("send_list: %-18"PRIu64" \n", lstack_stat->data.pkts.send_list);
+ printf("call_null: %-18"PRIu64" \n", lstack_stat->data.pkts.stack_stat.call_null);
+ printf("send_self_rpc: %-14"PRIu64" \n", lstack_stat->data.pkts.stack_stat.send_self_rpc);
}
static void gazelle_print_lstack_stat_detail(struct gazelle_stack_dfx_data *lstack_stat,
@@ -873,8 +869,8 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_
printf("Active Internet connections (servers and established)\n");
do {
printf("\n------ stack tid: %6u ------\n", stat->tid);
- printf("No. Proto recv_cnt recv_ring in_send send_ring sem_cnt Local Address "
- " Foreign Address State\n");
+ printf("No. Proto recv_cnt recv_ring in_send send_ring sem_cnt fd Local Address "
+ " Foreign Address State\n");
uint32_t unread_pkts = 0;
uint32_t unsend_pkts = 0;
for (i = 0; i < conn->conn_num && i < GAZELLE_LSTACK_MAX_CONN; i++) {
@@ -883,13 +879,13 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_
rip.s_addr = conn_info->rip;
lip.s_addr = conn_info->lip;
if ((conn_info->state == GAZELLE_ACTIVE_LIST) || (conn_info->state == GAZELLE_TIME_WAIT_LIST)) {
- printf("%-6utcp %-10u%-11u%-9u%-11u%-9d%s:%hu\t%s:%hu\t%s\n", i, conn_info->recv_cnt,
+ printf("%-6utcp %-10u%-11u%-9u%-11u%-9d%-7d%s:%hu\t %s:%hu\t %s\n", i, conn_info->recv_cnt,
conn_info->recv_ring_cnt, conn_info->in_send, conn_info->send_ring_cnt, conn_info->sem_cnt,
- inet_ntop(AF_INET, &lip, str_ip, sizeof(str_ip)), conn_info->l_port,
+ conn_info->fd, inet_ntop(AF_INET, &lip, str_ip, sizeof(str_ip)), conn_info->l_port,
inet_ntop(AF_INET, &rip, str_rip, sizeof(str_rip)), conn_info->r_port,
tcp_state_to_str(conn_info->tcp_sub_state));
} else if (conn_info->state == GAZELLE_LISTEN_LIST) {
- printf("%-6utcp %-50u%s:%hu\t0.0.0.0:*\t\tLISTEN\n", i, conn_info->recv_cnt,
+ printf("%-6utcp %-57u%s:%hu\t 0.0.0.0:*\t\t LISTEN\n", i, conn_info->recv_cnt,
inet_ntop(AF_INET, &lip, str_ip, sizeof(str_ip)), conn_info->l_port);
} else {
printf("Got unknow tcp conn::%s:%5hu, state:%u\n",
diff --git a/src/ltran/ltran_forward.c b/src/ltran/ltran_forward.c
index b264ad3..776692d 100644
--- a/src/ltran/ltran_forward.c
+++ b/src/ltran/ltran_forward.c
@@ -92,7 +92,7 @@ static __rte_always_inline void backup_bufs_enque_rx_ring(struct gazelle_stack *
struct rte_mbuf *free_buf[RING_MAX_SIZE];
flush_cnt = (stack->backup_pkt_cnt < RING_MAX_SIZE) ? stack->backup_pkt_cnt : RING_MAX_SIZE;
- free_cnt = rte_ring_cn_dequeue_burst(stack->rx_ring, (void **)free_buf, flush_cnt);
+ free_cnt = gazelle_ring_read(stack->rx_ring, (void **)free_buf, flush_cnt);
for (uint32_t j = 0; j < free_cnt; j++) {
index = (stack->backup_start + j) % backup_size;
@@ -102,7 +102,7 @@ static __rte_always_inline void backup_bufs_enque_rx_ring(struct gazelle_stack *
stack->stack_stats.rx += free_cnt;
stack->backup_pkt_cnt -= free_cnt;
stack->backup_start = (stack->backup_start + free_cnt) % backup_size;
- rte_ring_cn_enqueue(stack->rx_ring);
+ gazelle_ring_read_over(stack->rx_ring);
}
static __rte_always_inline void pktbufs_move_to_backup_bufs(struct gazelle_stack *stack, struct rte_mbuf **mbuf,
@@ -135,7 +135,7 @@ static __rte_always_inline uint32_t pkt_bufs_enque_rx_ring(struct gazelle_stack
struct rte_mbuf **cl_buffer = stack->pkt_buf;
struct rte_mbuf *free_buf[GAZELLE_PACKET_READ_SIZE];
- free_cnt = rte_ring_cn_dequeue_burst(stack->rx_ring, (void **)free_buf, stack->pkt_cnt);
+ free_cnt = gazelle_ring_read(stack->rx_ring, (void **)free_buf, stack->pkt_cnt);
stack->stack_stats.rx += free_cnt;
/* this prefetch and copy code, only 50~60 instruction, but never spend less than 70 cycle.
@@ -187,7 +187,7 @@ static __rte_always_inline uint32_t pkt_bufs_enque_rx_ring(struct gazelle_stack
}
if (likely(free_cnt != 0)) {
- rte_ring_cn_enqueue(stack->rx_ring);
+ gazelle_ring_read_over(stack->rx_ring);
}
return free_cnt;
@@ -520,14 +520,14 @@ static __rte_always_inline void tcp_hash_table_handle(struct gazelle_stack *stac
return;
}
- uint32_t num = rte_ring_cn_dequeue_burst(stack->reg_ring, pkts, PACKET_READ_SIZE);
+ uint32_t num = gazelle_ring_read(stack->reg_ring, pkts, PACKET_READ_SIZE);
for (uint32_t i = 0; i < num; i++) {
tcp_hash_table_modify(stack, pkts[i]);
pkts[i] = NULL;
}
- rte_ring_cn_enqueue(stack->reg_ring);
+ gazelle_ring_read_over(stack->reg_ring);
if (pthread_mutex_unlock(&sock_htable->mlock) != 0) {
LTRAN_WARN("write tcp_htable: unlock failed, errno %d\n", errno);
}
@@ -675,7 +675,7 @@ static __rte_always_inline void downstream_forward_one(struct gazelle_stack *sta
uint32_t used_cnt;
struct rte_mbuf *used_pkts[GAZELLE_PACKET_READ_SIZE];
- used_cnt = rte_ring_cn_dequeue_burst(stack->tx_ring, (void **)used_pkts, GAZELLE_PACKET_READ_SIZE);
+ used_cnt = gazelle_ring_read(stack->tx_ring, (void **)used_pkts, GAZELLE_PACKET_READ_SIZE);
if (used_cnt == 0) {
return;
}
@@ -686,7 +686,7 @@ static __rte_always_inline void downstream_forward_one(struct gazelle_stack *sta
if (ret != 0) {
/* free pkts that not have be sent. */
LTRAN_ERR("down alloc error, rx_pkts:%u ret=%d.\n", used_cnt, ret);
- rte_ring_cn_enqueue(stack->tx_ring);
+ gazelle_ring_read_over(stack->tx_ring);
stack->stack_stats.tx_drop += used_cnt;
rte_exit(EXIT_FAILURE, "down alloc error\n");
}
@@ -696,7 +696,7 @@ static __rte_always_inline void downstream_forward_one(struct gazelle_stack *sta
tx_bytes += used_pkts[tx_pkts]->data_len;
stack->stack_stats.tx_bytes += used_pkts[tx_pkts]->data_len;
}
- rte_ring_cn_enqueue(stack->tx_ring);
+ gazelle_ring_read_over(stack->tx_ring);
/* send packets anyway. */
tx_pkts = 0;
diff --git a/src/ltran/ltran_stat.c b/src/ltran/ltran_stat.c
index 7080424..c6805a6 100644
--- a/src/ltran/ltran_stat.c
+++ b/src/ltran/ltran_stat.c
@@ -25,6 +25,7 @@
#include "gazelle_dfx_msg.h"
#include "ltran_timer.h"
#include "ltran_ethdev.h"
+#include "dpdk_common.h"
#include "ltran_forward.h"
static uint64_t g_start_time_stamp = 0;
@@ -32,25 +33,11 @@ static int32_t g_start_latency = GAZELLE_OFF;
volatile int32_t g_ltran_stop_flag = GAZELLE_FALSE;
static struct statistics g_statistics;
-static uint32_t get_rx_ring_count(const struct rte_ring *r)
-{
- return rte_ring_count(r);
-}
-
uint64_t get_start_time_stamp(void)
{
return g_start_time_stamp;
}
-static uint32_t get_tx_ring_count(const struct rte_ring *r)
-{
- uint32_t prod_tail = r->prod.tail;
- uint32_t cons_head = r->cons.head;
-
- uint32_t count = (cons_head - prod_tail) & r->mask;
- return (count > r->capacity) ? r->capacity : count;
-}
-
void set_start_latency_flag(int32_t flag)
{
struct gazelle_instance_mgr *instance_mgr = get_instance_mgr();
@@ -203,8 +190,8 @@ static int32_t gazelle_filling_lstack_stat_total(struct gazelle_stat_lstack_tota
stat->latency_pkts = stack->stack_stats.latency_pkts;
stat->latency_total = stack->stack_stats.latency_total;
stat->reg_ring_cnt = rte_ring_cn_count(stack->reg_ring);
- stat->rx_ring_cnt = get_rx_ring_count(stack->rx_ring);
- stat->tx_ring_cnt = get_tx_ring_count(stack->tx_ring);
+ stat->rx_ring_cnt = gazelle_ring_readover_count(stack->rx_ring);
+ stat->tx_ring_cnt = gazelle_ring_readable_count(stack->tx_ring);
return GAZELLE_OK;
}
--
2.23.0
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/nlgwcy/gazelle_kylin_src.git
git@gitee.com:nlgwcy/gazelle_kylin_src.git
nlgwcy
gazelle_kylin_src
gazelle_kylin_src
master

搜索帮助