Exemple #1
0
static int
os_sem_take_timeout_sem__(os_sem_t sem, uint64_t usecs)
{
    AIM_TRUE_OR_DIE(!USES_EFD(sem), "timout_sem__ called while EFD in use.");

    if(usecs == 0) {
        /** Normal wait */
        return os_sem_take(sem);
    }
    else {

        struct timespec ts;
        timespec_init_timeout__(&ts, usecs);

        for(;;) {
            if(sem_timedwait(&sem->sem, &ts) == 0) {
                return 0;
            }
            switch(errno)
                {
                case EINTR:
                    break;
                case ETIMEDOUT:
                    return -1;

                case EINVAL:
                    AIM_DIE("Invalid or corrupted semaphore or the timespec was invalid in os_sem_take_timeout().");
                    break;
                default:
                    AIM_DIE("Unhandled error condition in os_sem_take() for errno=%{errno}", errno);
                    break;
                }
        }
    }
}
Exemple #2
0
int
os_sem_take(os_sem_t sem)
{
    VALIDATE(sem);

    for(;;) {

        if(USES_EFD(sem)) {
            return os_sem_take_timeout(sem, 0);
        }
        else {
            if(sem_wait(&sem->sem) == 0) {
                return 0;
            }
        }

        switch(errno)
            {
            case EINTR:
                break;
            case EINVAL:
                AIM_DIE("Invalid or corrupted semaphore in os_sem_take().");
                break;
            default:
                AIM_DIE("Unhandled error condition in os_sem_take(): errno=%s", strerror(errno));
                break;
            }
    }
}
Exemple #3
0
static int insert__(bighash_table_t *table, int count, biglist_t** entries)
{
    int c;
    for(c = 0; c < count; c++) {
        test_entry_t *te = aim_zmalloc(sizeof(*te));
        te->id = c;

        bighash_insert(table, &te->hash_entry, hash_id(te->id));
        if(entries) {
            *entries = biglist_prepend(*entries, te);
        }
        /** Make sure we can find it */
        test_entry_t *fe = find_by_id(table, te->id);
        if(fe == NULL) {
            AIM_DIE("inserted entry was not found, count=%d/%d", c, count);
        }
        if(fe != te) {
            AIM_DIE("Retreived pointer not equal.");
        }
        if(bighash_entry_count(table) != (c+1)) {
            AIM_DIE("Entry count mismatch: should be %d, reported as %d",
                    (c+1), bighash_entry_count(table));
        }
    }
    return 0;
}
Exemple #4
0
void
ivs_cli_init(const char *path)
{
    ucli_init();

    unlink(path);

    listen_socket = socket(AF_UNIX, SOCK_STREAM, 0);
    if (listen_socket < 0) {
        perror("socket (CLI)");
        abort();
    }

    struct sockaddr_un saddr;
    memset(&saddr, 0, sizeof(saddr));
    saddr.sun_family = AF_UNIX;
    strcpy(saddr.sun_path, path);

    if (bind(listen_socket, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
        perror("bind (CLI)");
        abort();
    }

    if (listen(listen_socket, LISTEN_BACKLOG) < 0) {
        perror("listen (CLI)");
        abort();
    }

    indigo_error_t rv = ind_soc_socket_register(listen_socket, listen_callback, NULL);
    if (rv < 0) {
        AIM_DIE("Failed to register CLI socket: %s", indigo_strerror(rv));
    }
}
Exemple #5
0
void
test_bucket(void)
{
    struct {
        uint32_t k;
        uint32_t bucket;
        uint32_t reverse;
    } tests[] = {
        { 0, 0, 0 },
        { 1, 1, 1 },
        { 2, 2, 2 },
        { 14, 14, 14 },
        { 15, 15, 15 },
        { 16, 16, 16 },
        { 17, 17, 17 },
        { 30, 30, 30 },
        { 31, 31, 31 },
        { 32, 32, 32 },
        { 33, 32, 32 },
        { 34, 33, 34 },
        { 62, 47, 62 },
        { 63, 47, 62 },
        { 64, 48, 64 },
        { 65, 48, 64 },
        { 66, 48, 64 },
        { 67, 48, 64 },
        { 68, 49, 68 },
        { UINT32_MAX, 463, 4160749568 },
    };

    int i;
    for (i = 0; i < AIM_ARRAYSIZE(tests); i++) {
        uint32_t actual = histogram_bucket(tests[i].k);
        if (tests[i].bucket != actual) {
            AIM_DIE("histogram_bucket test failed: k=%u expect=%u actual=%u",
                    tests[i].k, tests[i].bucket, actual);
        }

        AIM_ASSERT(tests[i].bucket == histogram_bucket(tests[i].reverse));

        actual = histogram_key(tests[i].bucket);
        if (tests[i].reverse != actual) {
            AIM_DIE("histogram_key test failed: bucket=%u expect=%u actual=%u",
                    tests[i].bucket, tests[i].reverse, actual);
        }
    }
}
Exemple #6
0
void *
aim_zmalloc(size_t size)
{
    void *ptr = AIM_CALLOC(1, size);
    if (ptr == NULL) {
        AIM_DIE("memory allocation failed");
    }
    return ptr;
}
Exemple #7
0
void *
aim_realloc(void *ptr, size_t size)
{
    ptr = AIM_REALLOC(ptr, size);
    if (ptr == NULL) {
        AIM_DIE("memory allocation failed");
    }
    return ptr;
}
Exemple #8
0
static void
check(struct histogram *hist, uint32_t k, uint32_t v)
{
    uint32_t i = histogram_bucket(k);
    AIM_ASSERT(i < HISTOGRAM_BUCKETS);
    uint32_t v2 = hist->counts[i];
    if (v != v2) {
        AIM_DIE("Expected %u at key %u (index %u), found %u", v, k, i, v2);
    }
}
static void
ind_soc_cfg_commit(void)
{
    aim_log_t *lobj;

    if ((lobj = aim_log_find("socketmanager")) == NULL) {
        AIM_DIE("Could not find log module");
    } else {
        lobj->common_flags = staged_config.log_flags;
    }
}
Exemple #10
0
static void*
sem_test_thread__(void* p)
{
    int rv;
    sem_test_t* t = (sem_test_t*)p;

    uint64_t t0 = aim_time_monotonic();
    rv = aim_sem_take_timeout(t->take, t->timeout);
    uint64_t t1 = aim_time_monotonic();

    uint64_t duration = t1 - t0;
    int64_t delta = t->timeout - duration;

    printf("%s: rv=% d timeout: %.8" PRId64 " duration: %.8" PRId64 " delta: % .8" PRId64 "\n", t->name, rv, t->timeout, duration, delta);

    if(rv == -1) {
        if(delta > 0) {
            AIM_DIE("%s: premature timeout.", t->name);
        }
        /* Arbitrary, within 30ms */
        if(delta < -30000 && t->timeout) {
            AIM_DIE("%s: timeout blown.", t->name);
        }
    }
    else if(rv == 0) {
        if(delta < 0 && t->timeout) {
            AIM_DIE("%s: waited longer than timeout.", t->name);
        }
        if(t->timeout_required) {
            AIM_DIE("%s: timeout was required.", t->name);
        }
        (*t->acquired)++;
    }

    if(t->give) {
        aim_sem_give(t->give);
    }
    return NULL;
}
indigo_error_t
indigo_port_stats_get_one(of_port_no_t port_no, of_port_stats_entry_t *port_stats)
{
    of_object_t props;
    of_object_t prop;
    of_port_stats_entry_properties_bind(port_stats, &props);
    of_port_stats_prop_ethernet_init(&prop, props.version, -1, 1);
    if (of_list_port_stats_prop_append_bind(&props, &prop) < 0) {
        AIM_DIE("unexpected error appending to port stats properties");
    }

    port_counters[port_no].stats++;
    return INDIGO_ERROR_NONE;
}
Exemple #12
0
void
ind_core_bsn_table_checksum_stats_request_handler(of_object_t *_obj,
                                                        indigo_cxn_id_t cxn_id)
{
    of_bsn_table_checksum_stats_request_t *obj = _obj;
    of_bsn_table_checksum_stats_reply_t *reply;
    of_list_bsn_table_checksum_stats_entry_t entries;
    of_bsn_table_checksum_stats_entry_t *entry;
    uint32_t xid;
    uint8_t table_id;

    reply = of_bsn_table_checksum_stats_reply_new(obj->version);
    AIM_TRUE_OR_DIE(reply != NULL);

    of_bsn_table_checksum_stats_request_xid_get(obj, &xid);
    of_bsn_table_checksum_stats_reply_xid_set(reply, xid);
    of_bsn_table_checksum_stats_reply_entries_bind(reply, &entries);

    entry = of_bsn_table_checksum_stats_entry_new(entries.version);
    AIM_TRUE_OR_DIE(entry != NULL);

    for (table_id = 0; table_id < FT_MAX_TABLES; table_id++) {
        ft_table_t *table = &ind_core_ft->tables[table_id];
        of_bsn_table_checksum_stats_entry_table_id_set(entry, table_id);
        of_bsn_table_checksum_stats_entry_checksum_set(entry, table->checksum);

        if (of_list_append(&entries, entry) < 0) {
            /* This entry didn't fit, send out the current message and
                * allocate a new one. */
            of_bsn_table_checksum_stats_reply_flags_set(
                reply, OF_STATS_REPLY_FLAG_REPLY_MORE);
            indigo_cxn_send_controller_message(cxn_id, reply);

            reply = of_bsn_table_checksum_stats_reply_new(obj->version);
            AIM_TRUE_OR_DIE(reply != NULL);

            of_bsn_table_checksum_stats_reply_xid_set(reply, xid);
            of_bsn_table_checksum_stats_reply_entries_bind(reply, &entries);

            if (of_list_append(&entries, entry) < 0) {
                AIM_DIE("unexpected failure appending single bsn_table_checksum stats entry");
            }
        }
    }

    of_object_delete(entry);

    indigo_cxn_send_controller_message(cxn_id, reply);
}
Exemple #13
0
os_sem_t
os_sem_create_flags(int count, uint32_t flags)
{
    os_sem_t s = aim_zmalloc(sizeof(*s));

    if(flags & OS_SEM_CREATE_F_TRUE_RELATIVE_TIMEOUTS) {
        s->efd = eventfd(count, EFD_SEMAPHORE | EFD_NONBLOCK);
        if(s->efd == -1) {
            AIM_DIE("eventfd() failed - %s", strerror(errno));
        }
    }
    else {
        s->efd = EFD_INVALID;
        sem_init(&s->sem, 0, count);
    }
    return s;
}
Exemple #14
0
static void
handle_lua_command_request(indigo_cxn_id_t cxn_id, of_object_t *msg)
{
    const int max_reply_size = UINT16_MAX -
                               of_object_fixed_len[msg->version][OF_BSN_LUA_COMMAND_REPLY];
    uint32_t xid;
    of_octets_t request_data;
    of_bsn_lua_command_request_xid_get(msg, &xid);
    of_bsn_lua_command_request_data_get(msg, &request_data);

    pipeline_lua_allocator_reset();
    void *request_buf = pipeline_lua_allocator_dup(request_data.data, request_data.bytes);
    void *reply_buf = pipeline_lua_allocator_alloc(max_reply_size);

    lua_rawgeti(lua, LUA_REGISTRYINDEX, command_ref);
    lua_pushlightuserdata(lua, request_buf);
    lua_pushinteger(lua, request_data.bytes);
    lua_pushlightuserdata(lua, reply_buf);
    lua_pushinteger(lua, max_reply_size);

    if (lua_pcall(lua, 4, 1, 0) != 0) {
        AIM_LOG_ERROR("Failed to execute command xid=%#x: %s", xid, lua_tostring(lua, -1));
        indigo_cxn_send_error_reply(
            cxn_id, msg, OF_ERROR_TYPE_BAD_REQUEST, OF_REQUEST_FAILED_EPERM);
        return;
    }

    int reply_size = lua_tointeger(lua, 0);
    AIM_TRUE_OR_DIE(reply_size >= 0 && reply_size < max_reply_size);
    lua_settop(lua, 0);

    of_object_t *reply = of_bsn_lua_command_reply_new(msg->version);
    of_bsn_lua_command_reply_xid_set(reply, xid);
    of_octets_t reply_data = { .data = reply_buf, .bytes = reply_size };
    if (of_bsn_lua_command_reply_data_set(reply, &reply_data) < 0) {
        AIM_DIE("Unexpectedly failed to set data in of_bsn_lua_command_reply");
    }

    indigo_cxn_send_controller_message(cxn_id, reply);
}
Exemple #15
0
void
ind_cxn_bundle_ctrl_handle(connection_t *cxn, of_object_t *obj)
{
    uint32_t bundle_id;
    uint16_t ctrl_type;
    uint16_t flags;
    uint16_t err_code = OFPBFC_UNKNOWN;

    of_bundle_ctrl_msg_bundle_id_get(obj, &bundle_id);
    of_bundle_ctrl_msg_bundle_ctrl_type_get(obj, &ctrl_type);
    of_bundle_ctrl_msg_flags_get(obj, &flags);

    bundle_t *bundle = find_bundle(cxn, bundle_id);

    if (ctrl_type == OFPBCT_OPEN_REQUEST) {
        if (bundle != NULL) {
            err_code = OFPBFC_BUNDLE_EXIST;
            goto error;
        }

        bundle = find_bundle(cxn, BUNDLE_ID_INVALID);
        if (bundle == NULL) {
            err_code = OFPBFC_OUT_OF_BUNDLES;
            goto error;
        }

        bundle->id = bundle_id;
        bundle->flags = flags;
        AIM_ASSERT(bundle->count == 0);
        AIM_ASSERT(bundle->allocated == 0);
        AIM_ASSERT(bundle->bytes == 0);
        AIM_ASSERT(bundle->msgs == NULL);
    } else if (ctrl_type == OFPBCT_CLOSE_REQUEST) {
        /* Ignored */
    } else if (ctrl_type == OFPBCT_COMMIT_REQUEST) {
        if (bundle == NULL) {
            err_code = OFPBFC_BAD_ID;
            goto error;
        }

        if (comparator && !(bundle->flags & OFPBF_ORDERED)) {
            qsort(bundle->msgs, bundle->count, sizeof(bundle->msgs[0]), compare_message);
        }

        struct bundle_task_state *state = aim_zmalloc(sizeof(*state));
        state->cxn_id = cxn->cxn_id;
        state->reply = of_object_dup(obj);
        of_bundle_ctrl_msg_bundle_ctrl_type_set(state->reply, OFPBCT_COMMIT_REPLY);
        state->id = bundle->id;
        state->count = bundle->count;
        state->offset = 0;
        state->msgs = bundle->msgs;

        if (ind_soc_task_register(bundle_task, state, IND_SOC_NORMAL_PRIORITY) < 0) {
            AIM_DIE("Failed to create long running task for bundle");
        }

        ind_cxn_pause(cxn);

        /* Transfer ownership of msgs to task */
        bundle->msgs = NULL;
        bundle->count = 0;

        free_bundle(bundle);

        /* Do not send reply yet */
        return;
    } else if (ctrl_type == OFPBCT_DISCARD_REQUEST) {
        if (bundle == NULL) {
            err_code = OFPBFC_BAD_ID;
            goto error;
        }

        free_bundle(bundle);
    } else {
        err_code = OFPBFC_BAD_TYPE;
        goto error;
    }

    /* Send reply */
    of_object_t *reply = of_object_dup(obj);
    /* Derive the reply subtype from the request */
    of_bundle_ctrl_msg_bundle_ctrl_type_set(reply, ctrl_type+1);
    indigo_cxn_send_controller_message(cxn->cxn_id, reply);
    return;

error:
    indigo_cxn_send_error_reply(
        cxn->cxn_id, obj,
        OF_ERROR_TYPE_BUNDLE_FAILED,
        err_code);
}
Exemple #16
0
static int
os_sem_take_timeout_efd__(os_sem_t sem, uint64_t usecs)
{
    AIM_TRUE_OR_DIE(USES_EFD(sem), "timeout_efd__ called when efd is not valid.");

    /** poll() with timeout (in ms) */
    struct pollfd fds;

    fds.fd = sem->efd;
    fds.events = POLLIN;
    fds.revents = 0;

    uint64_t t_start = os_time_monotonic();
    int timeout_ms;

    if(usecs == 0) {
        /* Infinite timeout value when calling poll() */
        timeout_ms = -1;
    }
    else {
        timeout_ms = usecs / 1000;
    }

    for(;;) {

        int rv = poll(&fds, 1, timeout_ms);

        if(rv == 0) {
            /* Timed out */
            return -1;
        }
        if(rv == 1) {
            if(fds.revents & POLLIN) {
                /* Descriptor Ready */
                uint64_t v;
                if(eventfd_read(sem->efd, &v) == 0) {
                    /* Acquired. */
                    return 0;
                }
                else {
                    /**
                     * Acquired by someone else.
                     * Retry handled along with EINTR below.
                     */
                }
            }
        }
        if(rv == 1 || errno == EINTR) {
            /*
             * Calculate remaining timeout (if necessary) and retry.
             */
            if(timeout_ms != -1) {
                uint64_t now = os_time_monotonic();
                if( (now - t_start) >= usecs ) {
                    /* Total timeout has elapsed */
                    return -1;
                }
                else {
                    /* Remaining time to wait. */
                    timeout_ms = (usecs - (now - t_start) + 999)/1000;
                }
            }
            continue;
        }
        else {
            AIM_DIE("Unexpected return value from poll(): %s", strerror(errno));
        }
    }
}
/* Parse a controller string like "tcp:127.0.0.1:6633". */
static indigo_error_t
parse_controller(struct controller *controller, cJSON *root)
{
    indigo_cxn_protocol_t proto;
    indigo_cxn_params_tcp_over_ipv4_t *params4;
    indigo_cxn_params_tcp_over_ipv6_t *params6;
    indigo_cxn_params_unix_t *params_unix;
    char *proto_str = NULL, *ip = NULL, *unix_path = NULL;
    int port;
    int listen;
    int local;
    int prio;
    indigo_error_t err;

    err = ind_cfg_lookup_string(root, "protocol", &proto_str);
    if (err == INDIGO_ERROR_NOT_FOUND) {
        /* Allow default protocol value */
        proto_str = "tcp";
    } else if (err < 0) {
        if (err == INDIGO_ERROR_PARAM) {
            AIM_LOG_ERROR("Config: 'protocol' must be a string");
        }
        return err;
    }

    if (strcmp(proto_str, "tcp") == 0) {
        proto = INDIGO_CXN_PROTO_TCP_OVER_IPV4;
    } else if (strcmp(proto_str, "tcp6") == 0) {
        proto = INDIGO_CXN_PROTO_TCP_OVER_IPV6;
    } else if (strcmp(proto_str, "tls") == 0) {
        proto = INDIGO_CXN_PROTO_TLS_OVER_IPV4;
    } else if (strcmp(proto_str, "tls6") == 0) {
        proto = INDIGO_CXN_PROTO_TLS_OVER_IPV6;
    } else if (strcmp(proto_str, "unix") == 0) {
        proto = INDIGO_CXN_PROTO_UNIX;
    } else {
        AIM_LOG_ERROR("Config: Invalid controller protocol: %s", proto_str);
        return INDIGO_ERROR_PARAM;
    }

    switch(proto) {
    case INDIGO_CXN_PROTO_TCP_OVER_IPV4:  /* fall-through */
    case INDIGO_CXN_PROTO_TCP_OVER_IPV6:  /* fall-through */
    case INDIGO_CXN_PROTO_TLS_OVER_IPV4:  /* fall-through */
    case INDIGO_CXN_PROTO_TLS_OVER_IPV6:
        err = ind_cfg_lookup_string(root, "ip_addr", &ip);
        if (err < 0) {
            if (err == INDIGO_ERROR_PARAM) {
                AIM_LOG_ERROR("Config: 'ip_addr' must be a string");
            } else if (err == INDIGO_ERROR_NOT_FOUND) {
                AIM_LOG_ERROR("Config: Missing 'ip_addr' in controller spec");
            }
            return err;
        }
        /*
         * WARNING: no validity checks for IP address.
         * Instead, they are performed by the cli front-end.
         */

        err = ind_cfg_lookup_int(root, "port", &port);
        if (err == INDIGO_ERROR_NOT_FOUND) {
            /* Allow default protocol value */
            port = 6633;
        } else if (err < 0) {
            if (err == INDIGO_ERROR_PARAM) {
                AIM_LOG_ERROR("Config: 'port' must be an integer");
            }
            return err;
        }
        if (port < 0 || port >= 0xffff) {
            AIM_LOG_ERROR("Config: Invalid controller port: %d", port);
            return INDIGO_ERROR_PARAM;
        }

        break;

    case INDIGO_CXN_PROTO_UNIX:
        err = ind_cfg_lookup_string(root, "unix_path", &unix_path);
        if (err < 0) {
            if (err == INDIGO_ERROR_PARAM) {
                AIM_LOG_ERROR("Config: 'unix_path' must be a string");
            } else if (err == INDIGO_ERROR_NOT_FOUND) {
                AIM_LOG_ERROR("Config: Missing 'unix_path' in controller spec");
            }
            return err;
        }
        break;

    default:
        AIM_DIE("Config: No handling for protocol %d", proto);
    }

    err = ind_cfg_lookup_bool(root, "listen", &listen);
    if (err == INDIGO_ERROR_NOT_FOUND) {
        listen = 0;
    } else if (err < 0) {
        if (err == INDIGO_ERROR_PARAM) {
            AIM_LOG_ERROR("Config: 'listen' must be a boolean");
        }
        return err;
    }

    err = ind_cfg_lookup_bool(root, "local", &local);
    if (err == INDIGO_ERROR_NOT_FOUND) {
        local = 0;
    } else if (err < 0) {
        if (err == INDIGO_ERROR_PARAM) {
            AIM_LOG_ERROR("Config: 'local' must be a boolean");
        }
        return err;
    }

    err = ind_cfg_lookup_int(root, "priority", &prio);
    if (err == INDIGO_ERROR_NOT_FOUND) {
        prio = 0;
    } else if (err < 0) {
        if (err == INDIGO_ERROR_PARAM) {
            AIM_LOG_ERROR("Config: 'priority' must be an integer");
        }
        return err;
    }

    /* populate 'controller' struct */
    switch (proto) {
    case INDIGO_CXN_PROTO_TCP_OVER_IPV4:  /* fall-through */
    case INDIGO_CXN_PROTO_TLS_OVER_IPV4:
        params4 = &controller->proto.tcp_over_ipv4;
        params4->protocol = proto;
        strncpy(params4->controller_ip, ip, sizeof(params4->controller_ip));
        params4->controller_port = port;
        break;
    case INDIGO_CXN_PROTO_TCP_OVER_IPV6:  /* fall-through */
    case INDIGO_CXN_PROTO_TLS_OVER_IPV6:
        params6 = &controller->proto.tcp_over_ipv6;
        params6->protocol = proto;
        strncpy(params6->controller_ip, ip, sizeof(params6->controller_ip));
        params6->controller_port = port;
        break;
    case INDIGO_CXN_PROTO_UNIX:
        params_unix = &controller->proto.unx;
        params_unix->protocol = proto;
        strncpy(params_unix->unix_path, unix_path, INDIGO_CXN_UNIX_PATH_LEN);
        break;
    default:
        AIM_DIE("Config: No handling for protocol %d", proto);
    }

    controller->config.listen = listen;
    controller->config.cxn_priority = prio;
    controller->config.local = local;
    controller->config.version = OFCONNECTIONMANAGER_CONFIG_OF_VERSION;

    if (!local) {
        controller->config.periodic_echo_ms = staged_config.keepalive_period_ms;
        controller->config.reset_echo_count = 3;
    } else {
        controller->config.periodic_echo_ms = 0;
        controller->config.reset_echo_count = 0;
    }

    return INDIGO_ERROR_NONE;
}
/*
 * Register a sensor
 * Caller must make sure that 1 sensor registered only once
 * If it calls this twice, it will get 2 oid entries
 * for the same sensor
 *
 * We want to keep this snmp code as simple as possible
 */
static int
onlp_snmp_sensor_reg__(int sensor_type,
                       onlp_snmp_sensor_t *sensor)
{
    oid otemp[] = { ONLP_SNMP_SENSOR_TEMP_OID };
    oid ofan[]  = { ONLP_SNMP_SENSOR_FAN_OID };
    oid opsu[]  = { ONLP_SNMP_SENSOR_PSU_OID };
    oid oled[]  = { ONLP_SNMP_SENSOR_LED_OID };
    oid omisc[] = { ONLP_SNMP_SENSOR_MISC_OID };
    oid *o;
    u_long o_len;
    int ret = MIB_REGISTRATION_FAILED;

    onlp_snmp_sensor_ctrl_t *ss_type = get_sensor_ctrl__(sensor_type);

    /* We start with Base 1 */
    AIM_TRUE_OR_DIE(onlp_snmp_sensor_type_valid(sensor_type));
    AIM_TRUE_OR_DIE(sensor);
    AIM_TRUE_OR_DIE(ss_type);

    switch(sensor_type)
        {
        case ONLP_SNMP_SENSOR_TYPE_TEMP:
            o = otemp;
            o_len = OID_LENGTH(otemp);

            /* Not init yet, init oid table */
            if (!ss_type->handlers) {
                ss_type->handler_cnt = sizeof(temp_handler_fn__) / sizeof(temp_handler_fn__[0]);
                ss_type->handlers    = temp_handler_fn__;
                snprintf(ss_type->name, sizeof(ss_type->name), "%s", "temp_table");
            }
            break;

        case ONLP_SNMP_SENSOR_TYPE_FAN:
            o = ofan;
            o_len = OID_LENGTH(ofan);

            /* Not init yet, init oid table */
            if (!ss_type->handlers) {
                ss_type->handler_cnt = sizeof(fan_handler_fn__) / sizeof(fan_handler_fn__[0]);
                ss_type->handlers    = fan_handler_fn__;
                snprintf(ss_type->name, sizeof(ss_type->name), "%s", "fan_table");
            }
            break;

        case ONLP_SNMP_SENSOR_TYPE_PSU:
            o = opsu;
            o_len = OID_LENGTH(opsu);

            /* Not init yet, init oid table */
            if (!ss_type->handlers) {
                ss_type->handler_cnt = sizeof(psu_handler_fn__) / sizeof(psu_handler_fn__[0]);
                ss_type->handlers    = psu_handler_fn__;
                snprintf(ss_type->name, sizeof(ss_type->name), "%s", "psu_table");

            }
            break;

        case ONLP_SNMP_SENSOR_TYPE_LED:
            o = oled;
            o_len = OID_LENGTH(oled);

            /* Not init yet, init oid table */
            if (!ss_type->handlers) {
                ss_type->handler_cnt = sizeof(led_handler_fn__) / sizeof(led_handler_fn__[0]);
                ss_type->handlers    = led_handler_fn__;
                snprintf(ss_type->name, sizeof(ss_type->name), "%s", "led_table");
            }
            break;

        case ONLP_SNMP_SENSOR_TYPE_MISC:
            o = omisc;
            o_len = OID_LENGTH(omisc);

            /* Not init yet, init oid table */
            if (!ss_type->handlers) {
                ss_type->handler_cnt = sizeof(misc_handler_fn__) / sizeof(misc_handler_fn__[0]);
                ss_type->handlers    = misc_handler_fn__;
                snprintf(ss_type->name, sizeof(ss_type->name), "%s", "misc_table");
            }
            break;

        default:
            AIM_DIE("Invalid sensor value.");
            break;
    }

    /*
     * sensor_cnt original is 0
     * When sensor_cnt == ONLP_SNMP_CONFIG_DEV_MAX_INDEX
     * We stop adding
     */
    if (ss_type->sensor_cnt < ONLP_SNMP_CONFIG_DEV_MAX_INDEX) {
        /* Device index equal to ss_type->sensor_cnt */
        ss_type->sensor_cnt++;

        /* This entry must be null */
        AIM_TRUE_OR_DIE(!ss_type->sensor_list[ss_type->sensor_cnt]);

        snmp_log(LOG_INFO, "init type=%d, index=%d, id=%d",
                 sensor_type, ss_type->sensor_cnt, sensor->sensor_id);

        onlp_snmp_sensor_t *ss = AIM_MALLOC(sizeof(onlp_snmp_sensor_t));
        AIM_TRUE_OR_DIE(ss);
        AIM_MEMCPY(ss, sensor, sizeof(*sensor));
        ss->sensor_type = sensor_type;
        ss->info_valid = 0;
        ss->last_update_time = 0;

        /* Assign sensor to the list */
        ss_type->sensor_list[ss_type->sensor_cnt] = ss;

    } else {
        snmp_log(LOG_ALERT,
                 "Failed to register sensor type=%d id=%d, resource limited",
                 sensor_type, sensor->sensor_id);
        return ret;
    }

    AIM_TRUE_OR_DIE(o_len == ONLP_SNMP_SENSOR_OID_LENGTH,
                    "invalid oid length=%d", o_len);

    ret = reg_snmp_sensor_helper__(sensor_type, o, o_len,
                                   ss_type->sensor_cnt);
    if (ret) {
        snmp_log(LOG_ALERT,
                 "Failed to register sensor type=%d id=%d, MIB_ERROR=%d",
                 sensor_type, sensor->sensor_id, ret);
    }

    return ret;
}
Exemple #19
0
int
aim_main(int argc, char* argv[])
{
    AIM_LOG_STRUCT_REGISTER();

    /*
     * We queue many (up to 20) 64KB messages before sending them on the socket
     * with a single writev(). After we free all the messages the malloc
     * implementation would see we have more than 128KB (the default trim value)
     * free and return it to the OS with a call to brk(). Every time we
     * allocate a new message we have to get the memory with brk() all over
     * again.
     *
     * Increasing the trim threshold above the size of our working set
     * eliminates this churn.
     */
    mallopt(M_TRIM_THRESHOLD, 2*1024*1024);

    loci_logger = ivs_loci_logger;

    core_cfg.expire_flows = 1;
    core_cfg.stats_check_ms = 900;
    core_cfg.disconnected_mode = INDIGO_CORE_DISCONNECTED_MODE_STICKY;

    parse_options(argc, argv);

    /* Setup logging from command line options */

    if (loglevel >= LOGLEVEL_DEFAULT) {
        aim_log_fid_set_all(AIM_LOG_FLAG_FATAL, 1);
        aim_log_fid_set_all(AIM_LOG_FLAG_ERROR, 1);
        aim_log_fid_set_all(AIM_LOG_FLAG_WARN, 1);
    }

    if (loglevel >= LOGLEVEL_VERBOSE) {
        aim_log_fid_set_all(AIM_LOG_FLAG_VERBOSE, 1);
    }

    if (loglevel >= LOGLEVEL_TRACE) {
        aim_log_fid_set_all(AIM_LOG_FLAG_TRACE, 1);
    }

    if (use_syslog) {
        aim_log_pvs_set_all(aim_pvs_syslog_open("ivs", LOG_NDELAY, LOG_DAEMON));
    }

    AIM_LOG_MSG("Starting %s (%s) pid %d", program_version, AIM_STRINGIFY(BUILD_ID), getpid());

    /* Initialize all modules */

    if (ind_soc_init(&soc_cfg) < 0) {
        AIM_LOG_FATAL("Failed to initialize Indigo socket manager");
        return 1;
    }

    if (ind_cxn_init(&cxn_cfg) < 0) {
        AIM_LOG_FATAL("Failed to initialize Indigo connection manager");
        return 1;
    }

    if (ind_core_init(&core_cfg) < 0) {
        AIM_LOG_FATAL("Failed to initialize Indigo core module");
        return 1;
    }

    if (ind_ovs_init(datapath_name, max_flows) < 0) {
        AIM_LOG_FATAL("Failed to initialize OVSDriver module");
        return 1;
    }

    if (lacpa_init() < 0) {
        AIM_LOG_FATAL("Failed to initialize LACP Agent module");
        return 1;
    }

    if (lldpa_system_init() < 0) {
        AIM_LOG_FATAL("Failed to initialize LLDP Agent module");
        return 1;
    }

    if (arpa_init() < 0) {
        AIM_LOG_FATAL("Failed to initialize ARP Agent module");
        return 1;
    }

    if (router_ip_table_init() < 0) {
        AIM_LOG_FATAL("Failed to initialize Router IP table module");
        return 1;
    }

    if (icmpa_init() < 0) {
        AIM_LOG_FATAL("Failed to initialize ICMP Agent module");
        return 1;
    }

    if (dhcpra_system_init() < 0) {
        AIM_LOG_FATAL("Failed to initialize DHCP relay table and agent module");
        return 1;
    }

    if (enable_tunnel) {
        if (ind_ovs_tunnel_init() < 0) {
            AIM_LOG_FATAL("Failed to initialize tunneling");
            return 1;
        }
    }

    if (pipeline == NULL) {
        if (openflow_version == NULL || !strcmp(openflow_version, "1.0")) {
            pipeline = "standard-1.0";
        } else if (!strcmp(openflow_version, "1.3")) {
            pipeline = "standard-1.3";
        } else {
            AIM_DIE("unexpected OpenFlow version");
        }
    }

    AIM_LOG_INFO("Initializing forwarding pipeline '%s'", pipeline);
    indigo_error_t rv = pipeline_set(pipeline);
    if (rv < 0) {
        AIM_LOG_FATAL("Failed to set pipeline: %s", indigo_strerror(rv));
        return 1;
    }

#if 0
    /* TODO Configuration module installs its own SIGHUP handler. */
    if (ind_cfg_init() < 0) {
        AIM_LOG_FATAL("Failed to initialize Indigo configuration module");
        return 1;
    }
#endif

    if (config_filename) {
        ind_cfg_filename_set(config_filename);
        if (ind_cfg_load() < 0) {
            AIM_LOG_FATAL("Failed to load configuration file");
            return 1;
        }
    }

    if (dpid) {
        indigo_core_dpid_set(dpid);
    }

    /* Enable all modules */

    if (ind_soc_enable_set(1) < 0) {
        AIM_LOG_FATAL("Failed to enable Indigo socket manager");
        return 1;
    }

    if (ind_cxn_enable_set(1) < 0) {
        AIM_LOG_FATAL("Failed to enable Indigo connection manager");
        return 1;
    }

    if (ind_core_enable_set(1) < 0) {
        AIM_LOG_FATAL("Failed to enable Indigo core module");
        return 1;
    }

    /* Add interfaces from command line */
    {
        biglist_t *element;
        char *str;
        int index = 1;
        BIGLIST_FOREACH_DATA(element, interfaces, char *, str) {
            AIM_LOG_MSG("Adding interface %s (port %d)", str, index);
            if (indigo_port_interface_add(str, index, NULL)) {
                AIM_LOG_FATAL("Failed to add interface %s", str);
                return 1;
            }
            index++;
        }
    }
Exemple #20
0
int test_table_data__(bighash_table_t *table, biglist_t** entry_list)
{
    /* Make sure we can find all entries in the entry list */
    {
        biglist_t *ble;
        test_entry_t *te;
        BIGLIST_FOREACH_DATA(ble, *entry_list, test_entry_t*, te) {
            test_entry_t *fe = find_by_id(table, te->id);
            if(fe == NULL) {
                AIM_DIE("inserted entry (id=%d) was not found after filling table",
                        te->id);
            }
            else if(fe != te) {
                AIM_DIE("Retreived pointer does not match. (te=%p (%d), fe=%p (%d)",
                        te, te->id, fe, fe->id);
            }
        }
    }

    /* Make sure all elements in the list are enumerated */
    {
        bighash_iter_t iter;
        bighash_entry_t *e;
        int count = 0;
        for(e = bighash_iter_start(table, &iter); e; e = bighash_iter_next(&iter)) {
            test_entry_t *te = container_of(e, hash_entry, test_entry_t);

            if(te->found) {
                AIM_DIE("Entry %p:%d was already enumerated.", te, te->id);
            }
            te->found++;
            if(biglist_find(*entry_list, te) == NULL) {
                AIM_DIE("Entry %p:%d is not in the entry list.", te, te->id);
            }
            count++;
        }
        if(count != biglist_length(*entry_list)) {
            AIM_DIE("Enumeration error: count=%d, length=%d",
                    count, biglist_length(*entry_list));
        }
    }

    /* Remove from table */
    {
        biglist_t *ble;
        test_entry_t *te;
        int count = 1;
        BIGLIST_FOREACH_DATA(ble, *entry_list, test_entry_t*, te) {
            bighash_remove(table, &te->hash_entry);
            if(find_by_id(table, te->id) != NULL) {
                AIM_DIE("Removed entry was not removed.");
            }
            if(bighash_entry_count(table) != biglist_length(*entry_list)-count) {
                AIM_DIE("Entry count mismatch: hashcount=%d, listcount=%d",
                        bighash_entry_count(table), biglist_length(*entry_list)-count);
            }
            count++;
        }
    }

    /* Free entry list */
    biglist_free_all(*entry_list, aim_free);
    *entry_list = NULL;
    return 0;
}
Exemple #21
0
int main(int argc, char *argv[])
{
    biglist_t *entries = NULL;

    /** Basic Hashing -- statically allocated table */
    bighash_table_init_static(&static_table);
    insert__(&static_table, 10000, &entries);
    test_table_data__(&static_table, &entries);
    bighash_table_destroy(&static_table, NULL);

    /** Basic hashing -- dynamically allocated table */
    {
        bighash_table_t *dtable;
        dtable = bighash_table_create(64);
        insert__(dtable, 10000, &entries);
        test_table_data__(dtable, &entries);
        bighash_table_destroy(dtable, NULL);
    }

    /** Count and removal while iterating */
    {
        bighash_table_t *table;
        bighash_iter_t iter;
        bighash_entry_t *e;
        test_entry_t *te;
        int ecount=100;
        int count = 0;
        table = bighash_table_create(64);
        insert__(table, ecount, NULL);
        if(bighash_entry_count(table) != ecount) {
            AIM_DIE("Entry count mismatch: expected %d, got %d",
                    ecount, bighash_entry_count(table));
        }
        /* Iterate once, just counting */
        for(te = (test_entry_t*)bighash_iter_start(table, &iter);
            te; te = (test_entry_t*)bighash_iter_next(&iter)) {
            count++;
        }
        if(count != ecount) {
            AIM_DIE("Iteration count incorrect (%d)", count);
        }
        /* Iterate again, removing elements. Tests both iteration restart
         * and remove-while-iterating.
         */
        for(e = bighash_iter_start(table, &iter); e; e = bighash_iter_next(&iter)) {
            test_entry_t *te = container_of(e, hash_entry, test_entry_t);
            bighash_remove(table, &te->hash_entry);
            /* Clear the list links on this element to make sure the
             * removal was done properly. */
            memset(te, 0, sizeof(*te));
            aim_free(te);
        }
        if(bighash_entry_count(table) != 0) {
            AIM_DIE("Count is not zero after iterated removal (count=%d)",
                    bighash_entry_count(table));
        }
        bighash_table_destroy(table, NULL);
    }

    /** Migrating between tables */
    {
        bighash_table_t *src;
        bighash_table_t *dst;
        src = bighash_table_create(64);
        dst = bighash_table_create(128);
        insert__(src, 1000, &entries);
        bighash_entries_move(dst, src);
        if(bighash_entry_count(src) != 0) {
            AIM_DIE("Source table is not empty.");
        }
        bighash_table_destroy(src, NULL);
        test_table_data__(dst, &entries);
        bighash_table_destroy(dst, NULL);
    }

    /** Check utilization and automatic element destruction */
    bighash_table_init_static(&static_table);
    insert__(&static_table, 100000, 0);
    bighash_table_utilization_show(&static_table, &aim_pvs_stdout);
    bighash_table_destroy(&static_table, free_test_entry);

    test_template();

    return 0;
}
Exemple #22
0
static void
reset_lua(void)
{
    if (lua) {
        pipeline_lua_table_reset();
        pipeline_lua_stats_reset();
        lua_close(lua);
    }

    lua = luaL_newstate();
    if (lua == NULL) {
        AIM_DIE("failed to allocate Lua state");
    }

    luaL_openlibs(lua);

    /* Give Lua a pointer to the static context struct */
    context.valid = false;
    lua_pushlightuserdata(lua, &context);
    lua_setglobal(lua, "_context");

    /* Give Lua the names of all fields */
    lua_newtable(lua);
    int i = 0;
    while (pipeline_lua_field_names[i]) {
        lua_pushstring(lua, pipeline_lua_field_names[i]);
        lua_rawseti(lua, -2, i+1);
        i++;
    }
    lua_setglobal(lua, "field_names");

    lua_pushcfunction(lua, pipeline_lua_table_register);
    lua_setglobal(lua, "register_table");

    const struct builtin_lua *builtin_lua;
    for (builtin_lua = &pipeline_lua_builtin_lua[0];
            builtin_lua->name; builtin_lua++) {
        AIM_LOG_VERBOSE("Loading builtin Lua code %s", builtin_lua->name);

        char name[64];
        snprintf(name, sizeof(name), "=%s", builtin_lua->name);

        /* Parse */
        if (luaL_loadbuffer(lua, builtin_lua->start,
                            builtin_lua->end-builtin_lua->start,
                            name) != 0) {
            AIM_DIE("Failed to load built-in Lua code %s: %s",
                    builtin_lua->name, lua_tostring(lua, -1));
        }

        /* Execute */
        if (lua_pcall(lua, 0, 0, 0) != 0) {
            AIM_DIE("Failed to execute built-in Lua code %s: %s",
                    builtin_lua->name, lua_tostring(lua, -1));
        }
    }

    /* Store a reference to process() so we can efficiently retrieve it */
    lua_getglobal(lua, "process");
    AIM_ASSERT(lua_isfunction(lua, -1));
    process_ref = luaL_ref(lua, LUA_REGISTRYINDEX);

    /* Store a reference to command() so we can efficiently retrieve it */
    lua_getglobal(lua, "command");
    AIM_ASSERT(lua_isfunction(lua, -1));
    command_ref = luaL_ref(lua, LUA_REGISTRYINDEX);

    /* Store a reference to pktin() so we can efficiently retrieve it */
    lua_getglobal(lua, "pktin");
    AIM_ASSERT(lua_isfunction(lua, -1));
    pktin_ref = luaL_ref(lua, LUA_REGISTRYINDEX);

    lua_pushinteger(lua, ind_ovs_pktin_socket_netlink_port(&pktin_soc));
    lua_setglobal(lua, "netlink_port");
}
void
ind_core_bsn_flow_checksum_bucket_stats_request_handler(of_object_t *_obj,
                                                        indigo_cxn_id_t cxn_id)
{
    of_bsn_flow_checksum_bucket_stats_request_t *obj = _obj;
    of_bsn_flow_checksum_bucket_stats_reply_t *reply;
    of_list_bsn_flow_checksum_bucket_stats_entry_t entries;
    of_bsn_flow_checksum_bucket_stats_entry_t *entry;
    uint32_t xid;
    uint8_t table_id;
    ft_table_t *table;
    int bucket_idx;

    of_bsn_flow_checksum_bucket_stats_request_table_id_get(obj, &table_id);

    if (table_id >= FT_MAX_TABLES) {
        AIM_LOG_WARN("Invalid table ID %u", table_id);
        indigo_cxn_send_error_reply(cxn_id, obj,
                                    OF_ERROR_TYPE_BAD_REQUEST,
                                    OF_REQUEST_FAILED_EPERM);
        return;
    }

    table = &ind_core_ft->tables[table_id];

    reply = of_bsn_flow_checksum_bucket_stats_reply_new(obj->version);
    AIM_TRUE_OR_DIE(reply != NULL);

    of_bsn_flow_checksum_bucket_stats_request_xid_get(obj, &xid);
    of_bsn_flow_checksum_bucket_stats_reply_xid_set(reply, xid);
    of_bsn_flow_checksum_bucket_stats_reply_entries_bind(reply, &entries);

    entry = of_bsn_flow_checksum_bucket_stats_entry_new(entries.version);
    AIM_TRUE_OR_DIE(entry != NULL);

    for (bucket_idx = 0; bucket_idx < table->checksum_buckets_size; bucket_idx++) {
        of_bsn_flow_checksum_bucket_stats_entry_checksum_set(
            entry, table->checksum_buckets[bucket_idx]);

        if (of_list_append(&entries, entry) < 0) {
            /* This entry didn't fit, send out the current message and
                * allocate a new one. */
            of_bsn_flow_checksum_bucket_stats_reply_flags_set(
                reply, OF_STATS_REPLY_FLAG_REPLY_MORE);
            indigo_cxn_send_controller_message(cxn_id, reply);

            reply = of_bsn_flow_checksum_bucket_stats_reply_new(obj->version);
            AIM_TRUE_OR_DIE(reply != NULL);

            of_bsn_flow_checksum_bucket_stats_reply_xid_set(reply, xid);
            of_bsn_flow_checksum_bucket_stats_reply_entries_bind(reply, &entries);

            if (of_list_append(&entries, entry) < 0) {
                AIM_DIE("unexpected failure appending single bsn_flow_checksum_bucket stats entry");
            }
        }
    }

    of_object_delete(entry);

    indigo_cxn_send_controller_message(cxn_id, reply);
}
int
vpi_mmap_interface_create(vpi_interface_t** vi, char* args[], int flags,
                       const char* vpi_name_ptr)
{
    struct sockaddr_ll sockaddr;
    struct packet_mreq sockparams;
    struct tpacket_req treq;
    struct ifreq ifreq;
    vpi_interface_mmap_t* nvi = aim_zmalloc(sizeof(*nvi));
    char** arg = args;
    int version;
    int i;
    frame_control_t* fc;

    AIM_REFERENCE(flags);

    if(nvi == NULL) {
        VPI_MERROR("interface allocation failed for %s.",
                   vpi_name_ptr);
        return -1;
    }

    /*
     * Point our log_string to our name so we can use it immediately
     * in log messages.
     */
    nvi->log_string = vpi_name_ptr;


    /*
     * The first argument is the type -- skip for now
     */
    arg++;

    aim_strlcpy(nvi->interface_name, *arg, sizeof(nvi->interface_name));

    /* Create RAW socket */
    if((nvi->fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
        VPI_ERROR(nvi, "socket() failed: %s\n", strerror(errno));
        aim_free(nvi);
        return -1;
    }

    /* Set version */
    version = TPACKET_V2;
    if(setsockopt(nvi->fd, SOL_PACKET, PACKET_VERSION,
                  &version, sizeof(version)) < 0) {
        VPI_ERROR(nvi, "setsockopt() version failed: %s\n", strerror(errno));
        aim_free(nvi);
        return -1;
    }

    /*
     * Get the interface index for the requested interface, as specified
     * in the current argument.
     */
    VPI_MEMSET(&ifreq, 0, sizeof(ifreq));
    aim_strlcpy(ifreq.ifr_name, nvi->interface_name, IFNAMSIZ);
    if(ioctl(nvi->fd, SIOCGIFINDEX, &ifreq) < 0) {
        VPI_ERROR(nvi, "ioctl() failed: %s", strerror(errno));
        close(nvi->fd);
        aim_free(nvi);
        return -1;
    }
    nvi->ifindex = ifreq.ifr_ifindex;
    VPI_INFO(nvi, "ifndex is %d", nvi->ifindex);

    /* Set promisc */
    VPI_MEMSET(&sockparams, 0, sizeof(sockparams));
    sockparams.mr_type = PACKET_MR_PROMISC;
    sockparams.mr_ifindex = nvi->ifindex;
    if(setsockopt(nvi->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
                  (void *)&sockparams, sizeof(sockparams)) < 0) {
        VPI_ERROR(nvi, "setsockopt() promisc failed. %s\n", strerror(errno));
        close(nvi->fd);
        aim_free(nvi);
        return -1;
    }

    /* Set up rx_ring buffer */
    VPI_MEMSET(&treq, 0, sizeof(treq));
    treq.tp_block_size = BLOCK_SIZE;
    treq.tp_frame_size = FRAME_SIZE;
    treq.tp_block_nr = NUM_BLOCKS;
    treq.tp_frame_nr = NUM_FRAMES;;
    if(setsockopt(nvi->fd, SOL_PACKET, PACKET_RX_RING,
                  (void*)&treq , sizeof(treq)) < 0) {
        VPI_ERROR(nvi, "setsockopt() rx_ring failed. %s\n", strerror(errno));
        close(nvi->fd);
        aim_free(nvi);
        return -1;
    }

    /* If num blocks change, bail! */
    if(treq.tp_block_nr != NUM_BLOCKS) {
        AIM_DIE("Unhandled: RX_RING block number changed!\n");
    }

    /* Set up rx_ring */
    nvi->rx_ring.buf = mmap(NULL, BLOCK_SIZE*NUM_BLOCKS,
                            PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED,
                            nvi->fd, 0);
    if(nvi->rx_ring.buf == MAP_FAILED) {
        VPI_ERROR(nvi, "mmap() failed.\n");
        close(nvi->fd);
        aim_free(nvi);
        return -1;
    }

    /* Set up rx_ring and frame controls */
    nvi->rx_ring.current_frame = 0;
    for(i = 0; i < NUM_FRAMES; i++) {
        fc = &nvi->rx_ring.frames[i];
        fc->base = nvi->rx_ring.buf + (i*FRAME_SIZE);
    }

    /* Bind */
    VPI_MEMSET(&sockaddr, 0, sizeof(sockaddr));
    sockaddr.sll_family = AF_PACKET;
    sockaddr.sll_protocol = htons(ETH_P_ALL);
    sockaddr.sll_ifindex = nvi->ifindex;
    if(bind(nvi->fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
        VPI_ERROR(nvi, "bind() failed.\n");
        close(nvi->fd);
        aim_free(nvi);
        return -1;
    }

    nvi->interface.send = vpi_mmap_interface_send;
    nvi->interface.recv = vpi_mmap_interface_recv;
    nvi->interface.recv_ready = vpi_mmap_interface_recv_ready;
    nvi->interface.destroy = vpi_mmap_interface_destroy;
    nvi->interface.descriptor = vpi_mmap_interface_descriptor;

    *vi = (vpi_interface_t*)nvi;
    return 0;
}
Exemple #25
0
int
aim_main(int argc, char *argv[])
{
    set_crash_handler(crash_handler);

    AIM_LOG_STRUCT_REGISTER();

    loci_logger = ofagent_loci_logger;

    core_cfg.stats_check_ms = 900;

    parse_options(argc, argv);

    /* Setup logging from command line options */
    if (loglevel >= LOGLEVEL_DEFAULT) {
        aim_log_fid_set_all(AIM_LOG_FLAG_MSG, 1);
        aim_log_fid_set_all(AIM_LOG_FLAG_FATAL, 1);
        aim_log_fid_set_all(AIM_LOG_FLAG_ERROR, 1);
        aim_log_fid_set_all(AIM_LOG_FLAG_WARN, 1);
    }

    if (loglevel >= LOGLEVEL_VERBOSE) {
        aim_log_fid_set_all(AIM_LOG_FLAG_VERBOSE, 1);
    }

    if (loglevel >= LOGLEVEL_TRACE) {
        aim_log_fid_set_all(AIM_LOG_FLAG_TRACE, 1);
    }

    if (use_syslog) {
        aim_log_pvs_set_all(aim_pvs_syslog_open("ofagent", LOG_NDELAY, LOG_DAEMON));
    }

    create_pidfile();

    AIM_LOG_MSG("Starting ofagent %s (%s %s) pid %d",
            ofagent_version, ofagent_build_id, ofagent_build_os, getpid());

    /* Increase maximum number of file descriptors */
    struct rlimit rlim = {
        .rlim_cur = SOCKETMANAGER_CONFIG_MAX_SOCKETS,
        .rlim_max = SOCKETMANAGER_CONFIG_MAX_SOCKETS
    };
    if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
        AIM_LOG_WARN("Failed to increase RLIMIT_NOFILE");
    }

    /* Initialize all modules */
    if (ind_soc_init(&soc_cfg) < 0) {
        AIM_LOG_FATAL("Failed to initialize Indigo socket manager");
        return 1;
    }

    if (ind_cxn_init(&cxn_cfg) < 0) {
        AIM_LOG_FATAL("Failed to initialize Indigo connection manager");
        return 1;
    }

    if (ind_core_init(&core_cfg) < 0) {
        AIM_LOG_FATAL("Failed to initialize Indigo core module");
        return 1;
    }

    if (bcm_driver_init() < 0) {
        AIM_LOG_FATAL("Failed to initialize BCM driver");
        return 1;
    }

    if (pipeline == NULL) {
        if (openflow_version == NULL || !strcmp(openflow_version, "1.0")) {
            pipeline = "standard-1.0";
        } else if (!strcmp(openflow_version, "1.3")) {
            pipeline = "standard-1.3";
        } else {
            AIM_DIE("unexpected OpenFlow version");
        }
    }

    AIM_LOG_VERBOSE("Initializing forwarding pipeline '%s'", pipeline);
    indigo_error_t rv = pipeline_set(pipeline);
    if (rv < 0) {
        AIM_LOG_FATAL("Failed to set pipeline: %s", indigo_strerror(rv));
        return 1;
    }

    if (config_filename) {
        ind_cfg_filename_set(config_filename);
        if (ind_cfg_load() < 0) {
            AIM_LOG_FATAL("Failed to load configuration file");
            return 1;
        }
    }

    if (dpid) {
        indigo_core_dpid_set(dpid);
    }

    /* Enable all modules */
    if (ind_soc_enable_set(1) < 0) {
        AIM_LOG_FATAL("Failed to enable Indigo socket manager");
        return 1;
    }

    if (ind_cxn_enable_set(1) < 0) {
        AIM_LOG_FATAL("Failed to enable Indigo connection manager");
        return 1;
    }

    if (ind_core_enable_set(1) < 0) {
        AIM_LOG_FATAL("Failed to enable Indigo core module");
        return 1;
    }

    if (bcm_driver_enable_set(1) < 0) {
        AIM_LOG_FATAL("Failed to enable BCM driver");
        return 1;
    }

    /* Add controller from command line */
    {
        biglist_t *element;
        char *str;
        BIGLIST_FOREACH_DATA(element, controllers, char *, str) {
            AIM_LOG_VERBOSE("Adding controller %s", str);

            indigo_cxn_protocol_params_t proto;
            if (parse_controller(str, &proto, OF_TCP_PORT) < 0) {
                AIM_LOG_FATAL("Failed to parse controller string '%s'", str);
                return 1;
            }

            indigo_cxn_config_params_t config = {
                .version = OF_VERSION_1_0,
                .cxn_priority = 0,
                .local = 0,
                .listen = 0,
                .periodic_echo_ms = 2000,
                .reset_echo_count = 3,
            };

            indigo_controller_id_t id;
            if (indigo_controller_add(&proto, &config, &id) < 0) {
                AIM_LOG_FATAL("Failed to add controller %s", str);
                return 1;
            }
        }
    }

    ind_core_mfr_desc_set(mfr_desc);

    snprintf(sw_desc, sizeof(sw_desc),
            "ofagent %s %s %s", ofagent_version,
            ofagent_build_id, ofagent_build_os);
    ind_core_sw_desc_set(sw_desc);

    // TODO
    //read_hardware_version(hw_desc);
    ind_core_hw_desc_set(hw_desc);

    char hostname[256];
    char domainname[256];
    if (gethostname(hostname, sizeof(hostname))) {
        sprintf(hostname, "(unknown)");
    }
    if (getdomainname(domainname, sizeof(domainname))) {
        sprintf(domainname, "(unknown)");
    }
    snprintf(dp_desc, sizeof(dp_desc), "%s.%s pid %d",
             hostname, domainname, getpid());
    ind_core_dp_desc_set(dp_desc);

    AIM_LOG_INFO("Datapath description: %s", dp_desc);

    ind_core_serial_num_set(serial_num);

    /* The SIGHUP handler triggers sighup_callback to run in the main loop. */
    if ((sighup_eventfd = eventfd(0, 0)) < 0) {
        AIM_LOG_FATAL("Failed to allocate eventfd");
        abort();
    }
    signal(SIGHUP, sighup);
    if (ind_soc_socket_register(sighup_eventfd, sighup_callback, NULL) < 0) {
        abort();
    }

    /* The SIGTERM handler triggers sigterm_callback to run in the main loop. */
    if ((sigterm_eventfd = eventfd(0, 0)) < 0) {
        AIM_LOG_FATAL("Failed to allocate eventfd");
        abort();
    }
    signal(SIGTERM, sigterm);
    if (ind_soc_socket_register(sigterm_eventfd, sigterm_callback, NULL) < 0) {
        abort();
    }

    /* TODO Start handling upcalls */
    //ind_ovs_enable();

    //packet_trace_init(datapath_name);

    ind_soc_select_and_run(-1);

    AIM_LOG_MSG("Stopping ofagent %s", ofagent_version);

    ind_core_finish();
    bcm_driver_finish();
    ind_cxn_finish();
    ind_soc_finish();

    return 0;
}