(1 << 0)/*表示当前是server端*/ #define CLIB_SOCKET_F_IS_CLIENT (0 << 0)/*表示当前是client端*/ #define CLIB_SOCKET_F_RX_END_OF_FILE min_bytes); clib_error_t *(*close_func) (struct _socket_t * sock); clib_error_t *(*recvmsg_func) 1、初始化 __clib_export clib_error_t *clib_socket_init (clib_socket_t * s) 根据用户设置s的参数完成socket初始化动作,包含回调函数初始化 2、clib_socket_accept接收客户端连接 __clib_export clib_error_t * clib_socket_accept (clib_socket_t * server, * unix_cli_listen_read_ready (clib_file_t * uf) { unix_main_t *um = &unix_main; clib_file_main_t
_main_t :内存分配管理结构体; clib_valloc_chunk_t:内存块结构; 具体介绍如下: 接口api 1、向虚拟分配管理区添加一块内存区 void clib_valloc_add_chunk (clib_valloc_main_t * vam, clib_valloc_chunk_t * template) 参数说明: 1、clib_valloc_main_t * vam :指向内存分配器管理结构指针 2、内存分配器管理结构初始化 void clib_valloc_init (clib_valloc_main_t * vam, clib_valloc_chunk_t * template,int need_lock uword clib_valloc_alloc (clib_valloc_main_t * vam, uword size, int os_out_of_memory_on_failure 4 内存释放到内存管理结构 uword clib_valloc_free (clib_valloc_main_t * vam, uword baseva) 参数说明: 1、clib_valloc_main_t
) sm->log2_page_sz = CLIB_MEM_PAGE_SZ_DEFAULT; mfd = clib_mem_vm_create_fd (sm->log2_page_sz, format_clib_error, clib_mem_get_last_error ()); /* Set size */ if ((ftruncate (mfd, memory_size)) ) return clib_error_return (0, "stat segment mmap failure"); sys_page_sz = clib_mem_get_page_size (sizeof (clib_spinlock_t)); sm->locking_thread_index = ~0; sm->n_locks = 0; clib_spinlock_init ) sm->log2_page_sz = CLIB_MEM_PAGE_SZ_DEFAULT; 3、创建内存文件描述符:通过clib_mem_vm_create_fd()创建一个内存文件描述符(mfd
{ clib_bihash_kv_8_8_t kv = { .key = key, .value = 1 }; clib_bihash_kv_8_8_t value; if (! static clib_error_t * bihash_race_init (vlib_main_t *vm) { clib_bihash_init_8_8 (&br_bihash_8_8, "bihash_race (b->lock)) - { - volatile BVT (clib_bihash_bucket) * bv = b; - while (bv->lock) - CLIB_PAUSE (); - } + BV (clib_bihash_lock_bucket) (b); v = BV (clib_bihash_get_value) (h, b->offset); @@ -557,9 +552,11 @@ static inline int BV (clib_bihash_search_inline_2_with_hash) if (BV (clib_bihash_key_compare
clib_arch_is_big_endian) x = clib_byte_swap_u16 (x); return x; } always_inline u16 clib_big_to_host_u16 #define CLIB_CACHE_LINE_ROUND(x) ((x + CLIB_CACHE_LINE_BYTES - 1) & ~(CLIB_CACHE_LINE_BYTES - 1)) 下面是 ); \ _CLIB_PREFETCH (0, size, type); \ _CLIB_PREFETCH (1, size, type); \ _CLIB_PREFETCH void clib_prefetch_load (void *p) { CLIB_PREFETCH (p, CLIB_CACHE_LINE_BYTES, LOAD); } /**/ static_always_inline void clib_prefetch_store (void *p) { CLIB_PREFETCH (p, CLIB_CACHE_LINE_BYTES, STORE); } 协程相关api-longjmp
bm; clib_error_t *err = 0; clib_bitmap_t *bmp = 0, *bmp_has_memory = 0; u32 numa_node; vlib_buffer_pool_t (bmp, 0, 1); if (clib_bitmap_last_set (bmp) >= VLIB_BUFFER_MAX_NUMA_NODES) clib_panic ("system vlib_buffer_main_t *bm; clib_error_t *err = 0; clib_bitmap_t *bmp = 0, *bmp_has_memory = 0; u32 __clib_export clib_bitmap_t *os_get_online_cpu_node_bitmap () { #if __linux__ return clib_sysfs_read_bitmap __clib_export clib_bitmap_t *os_get_cpu_with_memory_bitmap () { #if __linux__ return clib_sysfs_read_bitmap
(error); goto done; } if ((error = vlib_log_init (vm))) { clib_error_report ( error); goto done; } if ((error = vlib_stats_init (vm))) { clib_error_report ( unformat (input, "seed %wd", &vm->random_seed)) vm->random_seed = clib_cpu_time_now (); clib_random_buffer_init unformat (input, "seed %wd", &vm->random_seed)) vm->random_seed = clib_cpu_time_now (); clib_random_buffer_init (vm); if (sub_error) clib_error_report (sub_error); } switch (clib_setjmp (&vm->main_loop_exit
(sizeof (clib_pmalloc_main_t), CLIB_CACHE_LINE_BYTES); memset (p, 0, sizeof (clib_pmalloc_main_t 函数分配一块对齐到缓存行大小的内存,用于物理内存分配器 clib_pmalloc_main_t。 p = clib_mem_alloc_aligned (sizeof (clib_pmalloc_main_t), CLIB_CACHE_LINE_BYTES); memset (p, 0, sizeof (clib_pmalloc_main_t)); 将分配的内存清零,并设置为 vpm->pmalloc_main。 调用 clib_pmalloc_init 函数初始化物理内存分配器,传入基地址和最大大小。
要初始化 clib_time_t 对象,请调用 clib_time_init(&clib_time_t对象)。 函数 clib_time_now() 可以返回自 VPP 启动以来的秒数,并且保证该计时是单调递增的,即使系统参考时钟发生变化也不会受到影响。 核心代码如下所示: /* 初始化时间基线,默认是UST-5时间*/ clib_timebase_init (tb, -5 /* EST */ , CLIB_TIMEBASE_DAYLIGHT_USA , &vm->clib_time); /* 设置夏令时缓存 */ now = clib_timebase_now (tb); /* 打印当前系统时间 */ fformat clib_timebase_init (tb, 7 /* EST */ , CLIB_TIMEBASE_DAYLIGHT_USA, &vm->clib_time); 测试结果如下,和系统时间一致
<Button Content="Button 3" Background="Orange" clib:OrbitPanel.Orbit="0" /> <Button Content ="Orange" clib:OrbitPanel.Orbit="0" /> <Button Content="Button 6" Background="Orange" clib <Button Content="Button 9" Background="Orange" clib:OrbitPanel.Orbit="0" /> <Button Content ="Blue" clib:OrbitPanel.Orbit="1" /> <Button Content="Button 12" Background="Blue" clib:OrbitPanel.Orbit <Button Content="Button 14" Background="Blue" clib:OrbitPanel.Orbit="1" /> </clib:OrbitPanel>
main_heap_log2_page_sz = CLIB_MEM_PAGE_SZ_DEFAULT; clib_mem_page_sz_t default_log2_hugepage_sz = CLIB_MEM_PAGE_SZ_UNKNOWN clib_cpu_supports_ ## a ()) \ { \ fprintf( * Manual since none of the clib infra has been bootstrapped yet. = CLIB_MEM_PAGE_SZ_UNKNOWN) clib_mem_set_log2_default_hugepage_size (default_log2_hugepage_sz); = CLIB_MEM_PAGE_SZ_UNKNOWN) clib_mem_set_log2_default_hugepage_size (default_log2_hugepage_sz);
= 0); /* 分配节点需要的空间,并且填充节点vlib_node_t 的字段 */ n = clib_mem_alloc_no_fail (sizeof (n[0])); clib_memset (log2_n_stack_bytes, clib_mem_get_log2_page_size ()); p = clib_mem_alloc_aligned ( sizeof (p[0]), CLIB_CACHE_LINE_BYTES); clib_memset (p, 0, sizeof (p[0])); p->log2_n_stack_bytes = log2_n_stack_bytes; p->stack = clib_mem_vm_map_stack (1ULL << log2_n_stack_bytes, CLIB_MEM_PAGE_SZ_DEFAULT ) clib_panic ("failed to allocate process stack (%d bytes)", 1ULL << log2_n_stack_bytes
(), vgm->configured_elog_ring_size); elog_enable_disable (vlib_get_elog_main (), 1); elog初始化逻辑 __clib_export void elog_init (elog_main_t * em, u32 n_events) { clib_memset (em, 0, sizeof (em[0])); em->lock = 0; if (n_events > 0) elog_alloc (em, n_events); clib_time_init (&em->cpu_timer); em-> ); if (stack == CLIB_MEM_VM_MAP_FAILED) clib_panic ("failed to allocate thread %u stack", thread_index 09、clib_calljmp逻辑介绍 clib_calljmp相关的操作逻辑:调用了clib_calljmp实现了协程,clib_calljmp函数会调用thread0做为入口函数: i = clib_calljmp
@param [out] v - bitmap的首地址 @param n_bits - 请求的bits数量 */ #define clib_bitmap_alloc(v,n_bits) \ */ always_inline uword * clib_bitmap_set (uword * ai, uword i, uword value) bitmap 获取指定bit位 /** Gets */ always_inline uword clib_bitmap_get (uword * ai, uword i) 设置或者获取一段范围内的bitmap数值 /* n_bits 必须小于等于64 * i :起始bit位置 */ always_inline uword clib_bitmap_get_multiple (uword * bitmap, uword i, uword n_bits) */ always_inline uword * clib_bitmap_set_multiple (uword * bitmap, uword i, uword value, uword n_bits
具体代码如下: clib_error_t * linux_epoll_input_init (vlib_main_t * vm) { linux_epoll_main_t *em; clib_file_main_t /*设置server及PF_local套接字*/ s->flags = CLIB_SOCKET_F_IS_SERVER | /* listen, don't connect */ CLIB_SOCKET_F_ALLOW_GROUP_WRITE; /* PF_LOCAL socket only */ /*socket 初始化*/ error (fm, &template); } 这里需要注意:clib_file_add 返回值是在file_mian->file_pool 内存池中的索引,因为unix cli server是不无需释放的, 但是并没有存储clib_file_add 的返回值,会导致pool资源泄漏问题。下面是enable/disable/enable tap-inject操作后信息:很明显已经存在资源泄漏。
(*file_update) (clib_file_t * file, clib_file_update_type_t update_type); } clib_file_main_t always_inline uword clib_file_add (clib_file_main_t * um, clib_file_t * template) 2、删除当前clib_file_t always_inline void clib_file_del (clib_file_main_t * um, clib_file_t * f) 3、设置当前索引对应的clib_file_t always_inline void clib_file_set_polling_thread (clib_file_main_t * um, uword index, u32 clib_file_main_t file_main; clib_error_t * linux_epoll_input_init (vlib_main_t * vm) { linux_epoll_main_t
. */ u32 tail_index; } clib_fifo_header_t; head_index : fifo中有效数据的第一个索引 tail_index: fifo中尾部元素索引,表示下一个可加数据的索引 always_inline uword clib_fifo_elts (void *v) { word l, r; clib_fifo_header_t *f = clib_fifo_header v) return 0; l = _clib_fifo_len (v); r = (word) f->tail_index - (word) f->head_index; r = 比如 clib_fifo_advance_tail(f,n_elts),elts 可以是正数也可以是负数。如果是负数的时候,相当于覆盖已有数据。但是需要主要不能超过现有fifo的已有数据的大小。
= b) { fa[a] = b; } return ; } int main() { ll t,u,v; ll n,m,croad,clib; scanf("%lld", &t); while(t--) { scanf("%lld %lld %lld %lld", &n, &m, &clib, &croad ); ll num = 0; num = n * clib; for(ll i = 1; i <= n; i ++) fa[i] = i; ; i ++) { scanf("%lld %lld", &u, &v); Un(u,v); } if(clib sum = 0; for(ll i = 1; i <= n; i ++) { if(fa[i] == i) sum += clib
在编码过程中,如需要申请内存,可以使用下面两个函数clib_mem_alloc()或者clib_mem_alloc_aligned()函数;两者的区别在后者可以指定一定的长度对齐(一般是cacheline /* Memory allocator which calls os_out_of_memory() when it fails */ __clib_export __clib_flatten void * clib_mem_alloc (uword size) { return clib_mem_heap_alloc_inline (0, size, CLIB_MEM_MIN_ALIGN, /* os_out_of_memory */ 1); } __clib_export __clib_flatten void * clib_mem_alloc_aligned (uword size, (cacheline1); volatile u64 tail; /* modified by dequeue side */ CLIB_CACHE_LINE_ALIGN_MARK (
这里是使用了cmake的configure_file来设置的CLIB_TARGET_TRIPLET。你可以通过下面链接来学习cmake的configure_file使用。 https://www.cnblogs.com/gaox97329498/p/10952732.html 1、在源码路径上通过grep -rn CLIB_TARGET_TRIPLET 查询宏定义的位置 /mnt/f/workspce/vpp/src$ grep -rn CLIB_TARGET_TRIPLET vppinfra/config.h.in:23:#define CLIB_TARGET_TRIPLET #ifndef included_clib_config_h #define included_clib_config_h #ifndef CLIB_LOG2_CACHE_LINE_BYTES #define CLIB_LOG2_CACHE_LINE_BYTES 6 #endif #define CLIB_TARGET_TRIPLET "x86_64-linux-gnu" #define CLIB_VECTOR_GROW_BY_ONE