static void ci_bonding_get_mcast_subs_entry_fn(ci_dllist* subscriptions, char* line, int line_len, void* arg) { struct ci_read_proc_net_igmp_state* state = (struct ci_read_proc_net_igmp_state*)arg; struct ci_bonding_mcast_subscription *sub; int len, ifindex; if( state->in_right_netdev ) { if( line[0] >= '0' && line[0] <= '9' ) /* Assume that if we were in the right net dev block and a new * block starts the new block is for a different net dev and so * no longer the right one. */ state->in_right_netdev = 0; else { /* Line should represent state of each maddr */ sub = kmalloc(sizeof(struct ci_bonding_mcast_subscription), GFP_KERNEL); if( sub != NULL ) { len = sscanf(line, " %x", &sub->maddr); /* TODO parse line further to generate more state here? */ if( len == 1 ) { ci_dllist_push(subscriptions, &sub->list_link); OO_DEBUG_BONDING(ci_log("Found maddr %x for net dev %d", sub->maddr, state->ifindex)); } else { kfree(sub); OO_DEBUG_BONDING(ci_log("Parse error (1) in line %s", line)); } } } } else if( line[0] >= '0' && line[0] <= '9' ) { /* Start of new device block */ len = sscanf(line, "%d", &ifindex); if( len == 1 ) { if( ifindex == state->ifindex ) state->in_right_netdev = 1; } else OO_DEBUG_BONDING(ci_log("Parse error (2) in line %s", line)); } }
static void ci_bonding_get_ifnames_entry_fn(ci_dllist* iflist, char* line, int line_len, void *arg) { char *next; struct ci_bonding_ifname *ifname; do { ifname = kmalloc(sizeof(struct ci_bonding_ifname), GFP_KERNEL); if( ifname == NULL) return; ci_assert(line != NULL); ci_assert(line_len); while( line_len > 0 && (*line == '\n' || *line == ' ' || *line == '\0') ) { ++line; --line_len; } if( line_len == 0 ) return; next = strnchr(line, line_len, ' '); if( next != NULL ) { ci_assert(next - line <= IFNAMSIZ); strncpy(ifname->ifname, line, next - line); ifname->ifname[next - line] = '\0'; next++; // move over space line_len -= (next - line); } else { strncpy(ifname->ifname, line, IFNAMSIZ); line_len = 0; } ci_dllist_push(iflist, &ifname->list_link); line = next; } while (line != NULL); }
/* This function assumes an option of the same form and types as * EF_TCP_FORCE_REUSEPORT */ static void get_env_opt_port_list(ci_uint64* opt, const char* name) { char *s; unsigned v; if( (s = getenv(name)) ) { /* The memory used for this list is never freed, as we need it * persist until the process terminates */ *opt = (ci_uint64)(ci_uintptr_t)malloc(sizeof(ci_dllist)); if( ! *opt ) log("Could not allocate memory for %s list", name); else { struct ci_port_list *curr; ci_dllist *opt_list = (ci_dllist*)(ci_uintptr_t)*opt; ci_dllist_init(opt_list); while( sscanf(s, "%u", &v) == 1 ) { curr = malloc(sizeof(struct ci_port_list)); if( ! curr ) { log("Could not allocate memory for %s list entry", name); break; } curr->port = v; if( curr->port != v ) { log("ERROR: %s contains value that is too large: %u", name, v); free(curr); } else { curr->port = htons(curr->port); ci_dllist_push(opt_list, &curr->link); } s = strchr(s, ','); if( s == NULL ) break; s++; } } } }
static void ci_bonding_get_lacp_active_slaves_entry_fn(ci_dllist* active_slaves, char* line, int line_len, void* arg) { int n, agg_id; char slave_name[IFNAMSIZ]; struct ci_bonding_ifname *ifname; struct ci_read_proc_net_bonding_state* state = (struct ci_read_proc_net_bonding_state*)arg; n = sscanf(line, " Aggregator ID: %d", &agg_id); if( n == 1 ) { if( state->agg_id == -1 ) state->agg_id = agg_id; else { if( state->current_slave[0] != '\0' ) { if( state->agg_id == agg_id ) { ifname = kmalloc(sizeof(struct ci_bonding_ifname), GFP_KERNEL); if( ifname != NULL ) { strcpy(ifname->ifname, state->current_slave); ci_dllist_push(active_slaves, &ifname->list_link); } } state->current_slave[0] = '\0'; } else { OO_DEBUG_BONDING(ci_log("Aggregator ID found without known slave")); } } } else { n = sscanf(line, "Slave Interface: %s", slave_name); if( n == 1 ) strcpy(state->current_slave, slave_name); } }
int ci_buddy_ctor2(ci_buddy_allocator* b, unsigned order, void* (*alloc_fn)(size_t), void (*free_fn)(void*)) { unsigned o; ci_assert(b); b->order = order; b->free_lists = (ci_dllist*) alloc_fn((order+1) * sizeof(ci_dllist)); if( b->free_lists == 0 ) goto fail1; b->links = (ci_dllink*) alloc_fn(ci_pow2(order) * sizeof(ci_dllink)); if( b->links == 0 ) goto fail2; b->orders = (ci_uint8*) alloc_fn(ci_pow2(order)); if( b->orders == 0 ) goto fail3; CI_DEBUG(CI_ZERO_ARRAY(b->links, ci_pow2(order))); for( o = 0; o <= b->order; ++o ) ci_dllist_init(b->free_lists + o); ci_dllist_push(FL(b, b->order), ADDR_TO_LINK(b, 0)); ci_assert(b->order < 255); b->orders[0] = (ci_uint8)b->order; ci_assert(!IS_BUSY(b, LINK_TO_ADDR(b, ci_dllist_head(FL(b, b->order))))); return 0; fail3: free_fn(b->links); fail2: free_fn(b->free_lists); fail1: return -ENOMEM; }