Пример #1
0
void 
cleanup_settings(struct SSettings* psettings)
{
    assert(psettings != NULL);
    
    if (psettings->values != NULL)
    {
        smap_destroy(psettings->values);
    }
    
    if (psettings->main_tg != NULL)
    {
        mist_tg_destroy_impl(psettings->main_tg);
    }
    
    if (psettings->path_tg != NULL)
    {
        mist_tg_destroy_impl(psettings->path_tg);
    }
    
    free(psettings->tpl_path);
    free(psettings->val_path);
    
    return;
}
Пример #2
0
/* Configure management interface as dhcp mode.
 * On success, returns CMD_SUCCESS. On failure, returns CMD_OVSDB_FAILURE.
 */
static int
mgmt_intf_set_dhcp()
{
    const struct ovsrec_system *row = NULL;
    struct ovsdb_idl_txn* status_txn = NULL;
    enum ovsdb_idl_txn_status status;
    struct smap smap = SMAP_INITIALIZER(&smap);

    status_txn = cli_do_config_start();
    if (NULL == status_txn)
    {
        VLOG_ERR(OVSDB_TXN_CREATE_ERROR);
        cli_do_config_abort(status_txn);
        return CMD_OVSDB_FAILURE;
    }

    row = ovsrec_system_first(idl);

    if (!row)
    {
        VLOG_ERR(OVSDB_ROW_FETCH_ERROR);
        cli_do_config_abort(status_txn);
        return CMD_OVSDB_FAILURE;
    }


 /* If current mode is static remove static configs from DB. */
    smap_clone(&smap, &row->mgmt_intf);
    if (is_mode_static(row))
    {
        mgmt_intf_clear_ipv4_config_db(row, &smap);
        mgmt_intf_clear_ipv6_config_db(row, &smap);
    }

    smap_replace(&smap,
                 SYSTEM_MGMT_INTF_MAP_MODE,
                 SYSTEM_MGMT_INTF_MAP_MODE_DHCP);

    ovsrec_system_set_mgmt_intf(row, &smap);
    smap_destroy(&smap);
    status = cli_do_config_finish(status_txn);
    if (TXN_SUCCESS == status || TXN_UNCHANGED == status)
    {
        return CMD_SUCCESS;
    }
    else
    {
        VLOG_ERR(OVSDB_TXN_COMMIT_ERROR);
        return CMD_OVSDB_FAILURE;
    }
}
Пример #3
0
static int
ecmp_config_set_status (bool status, const char * field)
{
  const struct ovsrec_system *ovs_row = NULL;
  enum ovsdb_idl_txn_status txn_status;
  struct ovsdb_idl_txn *status_txn = cli_do_config_start ();
  bool rc = false;
  struct smap smap_ecmp_config;

  if (status_txn == NULL)
    {
      VLOG_ERR (OVSDB_TXN_CREATE_ERROR);
      cli_do_config_abort (status_txn);
      return CMD_OVSDB_FAILURE;
    }

  /* Need to set ecmp_config status */
  ovs_row = ovsrec_system_first (idl);

  if (!ovs_row)
    {
      VLOG_ERR (OVSDB_ROW_FETCH_ERROR);
      cli_do_config_abort (status_txn);
      return CMD_OVSDB_FAILURE;
    }

  rc = smap_get_bool (&ovs_row->ecmp_config, field,
                      SYSTEM_ECMP_CONFIG_ENABLE_DEFAULT);

  if (rc != status)
    {
      smap_clone (&smap_ecmp_config, &ovs_row->ecmp_config);
      smap_replace (&smap_ecmp_config, field, status ? "true" : "false");
      VLOG_DBG ("%s Set the ecmp config to status = %s old state = %s",
                __func__, status ? "enabled" : "disabled",
                rc ? "enabled" : "disabled");
      ovsrec_system_set_ecmp_config (ovs_row, &smap_ecmp_config);
      smap_destroy (&smap_ecmp_config);
    }

  txn_status = cli_do_config_finish (status_txn);

  if (txn_status == TXN_SUCCESS || txn_status == TXN_UNCHANGED)
    return CMD_SUCCESS;
  else
    {
      VLOG_ERR (OVSDB_TXN_COMMIT_ERROR);
      return CMD_OVSDB_FAILURE;
    }
}
Пример #4
0
/*-----------------------------------------------------------------------------
| Function : sftp_server_enable_disable
| Responsibility : To enable/disable SFTP server.
| Parameters :
|     bool enable: If true, enable SFTP server and if false
|                  disable the SFTP server.
| Return : On success returns CMD_SUCCESS,
|          On failure returns CMD_OVSDB_FAILURE
-----------------------------------------------------------------------------*/
static int
sftp_server_enable_disable (bool enable)
{
    const struct ovsrec_system *row = NULL;
    enum ovsdb_idl_txn_status txn_status;
    struct ovsdb_idl_txn *status_txn = cli_do_config_start();
    struct smap smap;

    if (status_txn == NULL)
    {
        VLOG_ERR(OVSDB_TXN_CREATE_ERROR);
        cli_do_config_abort(status_txn);
        return CMD_OVSDB_FAILURE;
    }

    row = ovsrec_system_first(idl);

    if (!row)
    {
        VLOG_ERR(OVSDB_ROW_FETCH_ERROR);
        cli_do_config_abort(status_txn);
        return CMD_OVSDB_FAILURE;
    }

    smap_clone(&smap, &row->other_config);

    if (enable) {
        smap_replace(&smap, SFTP_SERVER_CONFIG, "true");
    } else {
        smap_replace(&smap, SFTP_SERVER_CONFIG, "false");
    }

    ovsrec_system_set_other_config(row, &smap);

    txn_status = cli_do_config_finish(status_txn);
    smap_destroy(&smap);

    if (txn_status == TXN_SUCCESS || txn_status == TXN_UNCHANGED)
    {
        return CMD_SUCCESS;
    }
    else
    {
        VLOG_ERR(OVSDB_TXN_COMMIT_ERROR);
        return CMD_OVSDB_FAILURE;
    }
}
Пример #5
0
/*-----------------------------------------------------------------------------
| Function       : udpfwd_globalconfig
| Responsibility : To enable/disable udp broadcast forwarding and dhcp-relay.
| Parameters     :
|        status  : If true, enable UDP broadcast forwarding/dhcp-relay and
|                  if false disable the UDP broadcast forwarding/dhcp-relay
| Return         : On success returns CMD_SUCCESS,
|                  On failure returns CMD_OVSDB_FAILURE
-----------------------------------------------------------------------------*/
int8_t udpfwd_globalconfig(const char *status)
{
    const struct ovsrec_system *ovs_row = NULL;
    struct ovsdb_idl_txn *status_txn = cli_do_config_start();
    struct smap smap_status_value;
    enum ovsdb_idl_txn_status txn_status;
    char *key = NULL;

    if (status_txn == NULL)
    {
        VLOG_ERR(OVSDB_TXN_CREATE_ERROR);
        cli_do_config_abort(status_txn);
        return CMD_OVSDB_FAILURE;
    }

    ovs_row = ovsrec_system_first(idl);
    if (!ovs_row) {
        VLOG_ERR(OVSDB_ROW_FETCH_ERROR);
        cli_do_config_abort(status_txn);
        return CMD_OVSDB_FAILURE;
    }

    key = SYSTEM_OTHER_CONFIG_MAP_UDP_BCAST_FWD_ENABLED;

    smap_clone(&smap_status_value, &ovs_row->other_config);

    /* Update the latest config status. */
    smap_replace(&smap_status_value, key, status);

    ovsrec_system_set_other_config(ovs_row, &smap_status_value);
    smap_destroy(&smap_status_value);
    txn_status = cli_do_config_finish(status_txn);

    if (txn_status == TXN_SUCCESS || txn_status == TXN_UNCHANGED)
    {
        return CMD_SUCCESS;
    }
    else
    {
        VLOG_ERR(OVSDB_TXN_COMMIT_ERROR);
        return CMD_OVSDB_FAILURE;
    }
}
Пример #6
0
/* Configuring management interface DNS server.
 * On success, returns CMD_SUCCESS. On failure, returns CMD_OVSDB_FAILURE.
 */
static int
mgmt_intf_set_dns(bool set, const char *dns1, const char *dns2)
{
    const struct ovsrec_system *row = NULL;
    struct smap smap = SMAP_INITIALIZER(&smap);
    const char *cfg_dns1 = NULL;
    const char *cfg_dns2 = NULL;
    struct ovsdb_idl_txn* status_txn = NULL;
    enum ovsdb_idl_txn_status status;

    status_txn = cli_do_config_start();
    if (NULL == status_txn)
    {
        VLOG_ERR(OVSDB_TXN_CREATE_ERROR);
        cli_do_config_abort(status_txn);
        return CMD_OVSDB_FAILURE;
    }

    row = ovsrec_system_first(idl);

    if (!row)
    {
        VLOG_ERR(OVSDB_ROW_FETCH_ERROR);
        cli_do_config_abort(status_txn);
        return CMD_OVSDB_FAILURE;
    }

    smap_clone(&smap, &row->mgmt_intf);

    /* Handle primary DNS server configuration. */
    if (set)
    {
        smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_DNS_SERVER_1, dns1);

        if (dns2)
        {
            smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_DNS_SERVER_2, dns2);
        }
        else
        {
            smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_DNS_SERVER_2,
                                            MGMT_INTF_DEFAULT_IP);
        }
    }
    else
    {
        cfg_dns1 = smap_get(&smap, SYSTEM_MGMT_INTF_MAP_DNS_SERVER_1);
        if (!cfg_dns1 || strcmp(dns1, cfg_dns1) != 0)
        {
            vty_out(vty, "  %s %s", OVSDB_INVALID_VALUE_ERROR, VTY_NEWLINE);
            cli_do_config_abort(status_txn);
            smap_destroy(&smap);
            return CMD_SUCCESS;
        }

        cfg_dns2 = smap_get(&smap, SYSTEM_MGMT_INTF_MAP_DNS_SERVER_2);
        if (dns2)
        {
            if (!cfg_dns2 || strcmp(dns2, cfg_dns2) != 0)
            {
                vty_out(vty, "  %s %s", OVSDB_INVALID_VALUE_ERROR, VTY_NEWLINE);
                cli_do_config_abort(status_txn);
                smap_destroy(&smap);
                return CMD_SUCCESS;
            }

            smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_DNS_SERVER_2,
                                              MGMT_INTF_DEFAULT_IP);
        }
        else if (cfg_dns2 && strcmp(cfg_dns2, MGMT_INTF_DEFAULT_IP) != 0)
        {
            vty_out(vty, "  %s %s", OVSDB_DNS_DEPENDENCY_ERROR, VTY_NEWLINE);
            cli_do_config_abort(status_txn);
            smap_destroy(&smap);
            return CMD_SUCCESS;
        }

        smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_DNS_SERVER_1,
                                              MGMT_INTF_DEFAULT_IP);
    }

    ovsrec_system_set_mgmt_intf(row, &smap);

    smap_destroy(&smap);

    status = cli_do_config_finish(status_txn);
    if (TXN_SUCCESS == status || TXN_UNCHANGED == status)
    {
        return CMD_SUCCESS;
    }
    else
    {
        VLOG_ERR(OVSDB_TXN_COMMIT_ERROR);
        return CMD_OVSDB_FAILURE;
    }
}
Пример #7
0
/* Configuring IPv6 default gateway on management interface.
 * On success, returns CMD_SUCCESS. On failure, returns CMD_OVSDB_FAILURE.
 */
static int
mgmt_intf_set_default_gw_ipv6(bool set, const char *gw_v6)
{
    const struct ovsrec_system *row = NULL;
    struct smap smap = SMAP_INITIALIZER(&smap);
    const char *cfg_gw = NULL;
    struct ovsdb_idl_txn* status_txn = NULL;
    enum ovsdb_idl_txn_status status;

    if (!is_valid_ip_address(gw_v6))
    {
        vty_out(vty, "  %s %s", OVSDB_INVALID_IPV4_IPV6_ERROR,VTY_NEWLINE);
        return CMD_SUCCESS;
    }

    status_txn = cli_do_config_start();
    if (NULL == status_txn)
    {
        VLOG_ERR(OVSDB_TXN_CREATE_ERROR);
        cli_do_config_abort(status_txn);
        return CMD_OVSDB_FAILURE;
    }

    row = ovsrec_system_first(idl);

    if (!row)
    {
        VLOG_ERR(OVSDB_ROW_FETCH_ERROR);
        cli_do_config_abort(status_txn);
        return CMD_OVSDB_FAILURE;
    }

    if (!is_mode_static(row))
    {
        vty_out(vty, "  %s %s", OVSDB_MODE_ERROR, VTY_NEWLINE);
        cli_do_config_abort(status_txn);
        return CMD_SUCCESS;
    }

    smap_clone(&smap, &row->mgmt_intf);

    if(!smap_get(&smap, SYSTEM_MGMT_INTF_MAP_IPV6))
    {
        vty_out(vty, "  %s %s", OVSDB_NO_IP_ERROR, VTY_NEWLINE);
        cli_do_config_abort(status_txn);
        smap_destroy(&smap);
        return CMD_SUCCESS;
    }

    if (set)
    {
        smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_DEFAULT_GATEWAY_V6, gw_v6);
    }
    else
    {
        cfg_gw = smap_get(&smap, SYSTEM_MGMT_INTF_MAP_DEFAULT_GATEWAY_V6);
        if (!cfg_gw || strcmp(gw_v6, cfg_gw) != 0)
        {
            vty_out(vty, "  %s %s", OVSDB_INVALID_VALUE_ERROR, VTY_NEWLINE);
            cli_do_config_abort(status_txn);
            smap_destroy(&smap);
            return CMD_SUCCESS;
        }

        smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_DEFAULT_GATEWAY_V6,
                                            MGMT_INTF_DEFAULT_IPV6);

    }

    ovsrec_system_set_mgmt_intf(row, &smap);

    smap_destroy(&smap);

    status = cli_do_config_finish(status_txn);
    if (TXN_SUCCESS == status || TXN_UNCHANGED == status)
    {
        return CMD_SUCCESS;
    }
    else
    {
        VLOG_ERR(OVSDB_TXN_COMMIT_ERROR);
        return CMD_OVSDB_FAILURE;
    }
}
Пример #8
0
/* Configuring static ip on management interface.
 * On success, returns CMD_SUCCESS. On failure, returns CMD_OVSDB_FAILURE.
 */
static int
mgmt_intf_set_static(bool set, const char *ip, enum ip_type type)
{
    const struct ovsrec_system *row = NULL;
    struct smap smap = SMAP_INITIALIZER(&smap);
    struct ovsdb_idl_txn* status_txn = NULL;
    enum ovsdb_idl_txn_status status;

    const char *subnet = NULL;
    const char *ip_addr = NULL;
    unsigned short subnet_in = 0;
    char buf[MAX_IPV4_OR_IPV6_SUBNET_CIDR_STR_LEN];

    if (!is_valid_ip_address(ip))
    {
        vty_out(vty, "  %s %s", OVSDB_INVALID_IPV4_IPV6_ERROR, VTY_NEWLINE);
        return CMD_SUCCESS;
    }

    memset(buf, 0, MAX_IPV4_OR_IPV6_SUBNET_CIDR_STR_LEN);
    strncpy(buf, ip, MAX_IPV4_OR_IPV6_SUBNET_CIDR_STR_LEN);
    ip_addr   = strtok(buf, "/");
    subnet    = strtok(NULL, "\0");
    subnet_in = atoi(subnet);

    if (IPV4 == type)
    {
        if (IS_INVALID_IPV4_SUBNET(subnet_in))
        {
            vty_out(vty, "  %s %s", OVSDB_INVALID_SUBNET_ERROR, VTY_NEWLINE);
            return CMD_SUCCESS;
        }
    }else if (IPV6 == type) {
        if (IS_INVALID_IPV6_SUBNET(subnet_in))
        {
            vty_out(vty, "  %s %s", OVSDB_INVALID_SUBNET_ERROR, VTY_NEWLINE);
            return CMD_SUCCESS;
        }
    }


    status_txn = cli_do_config_start();
    if (NULL == status_txn)
    {
        VLOG_ERR(OVSDB_TXN_CREATE_ERROR);
        cli_do_config_abort(status_txn);
        return CMD_OVSDB_FAILURE;
    }

    row = ovsrec_system_first(idl);

    if (!row)
    {
        VLOG_ERR(OVSDB_ROW_FETCH_ERROR);
        cli_do_config_abort(status_txn);
        return CMD_OVSDB_FAILURE;
    }

    smap_clone(&smap, &row->mgmt_intf);

    if (set)
        smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_MODE,
                            SYSTEM_MGMT_INTF_MAP_MODE_STATIC);

    if (IPV4 == type) {
        if (set)
        {
            smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_IP, ip_addr);
            smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_SUBNET_MASK, subnet);
        }
        else
        {
            if (mgmt_intf_remove_static_ipv4_address(&smap, ip_addr, subnet)
                                                               != CMD_SUCCESS)
            {
                cli_do_config_abort(status_txn);
                smap_destroy(&smap);
                return CMD_SUCCESS;
            }
        }
    }else if (IPV6 == type) {
        if (set)
            smap_replace(&smap, SYSTEM_MGMT_INTF_MAP_IPV6, ip);
        else
        {
            if (mgmt_intf_remove_static_ipv6_address(&smap, ip) != CMD_SUCCESS)
            {
                cli_do_config_abort(status_txn);
                smap_destroy(&smap);
                return CMD_SUCCESS;
            }
        }
    }

    ovsrec_system_set_mgmt_intf(row, &smap);

    smap_destroy(&smap);

    status = cli_do_config_finish(status_txn);
    if (TXN_SUCCESS == status || TXN_UNCHANGED == status)
    {
        return CMD_SUCCESS;
    }
    else
    {
        VLOG_ERR(OVSDB_TXN_COMMIT_ERROR);
        return CMD_OVSDB_FAILURE;
    }
}
Пример #9
0
/* Returns this chassis's Chassis record, if it is available and is currently
 * amenable to a transaction. */
const struct sbrec_chassis *
chassis_run(struct controller_ctx *ctx, const char *chassis_id,
            const struct ovsrec_bridge *br_int)
{
    if (!ctx->ovnsb_idl_txn) {
        return NULL;
    }

    const struct ovsrec_open_vswitch *cfg;
    const char *encap_type, *encap_ip;
    static bool inited = false;

    cfg = ovsrec_open_vswitch_first(ctx->ovs_idl);
    if (!cfg) {
        VLOG_INFO("No Open_vSwitch row defined.");
        return NULL;
    }

    encap_type = smap_get(&cfg->external_ids, "ovn-encap-type");
    encap_ip = smap_get(&cfg->external_ids, "ovn-encap-ip");
    if (!encap_type || !encap_ip) {
        VLOG_INFO("Need to specify an encap type and ip");
        return NULL;
    }

    char *tokstr = xstrdup(encap_type);
    char *save_ptr = NULL;
    char *token;
    uint32_t req_tunnels = 0;
    for (token = strtok_r(tokstr, ",", &save_ptr); token != NULL;
         token = strtok_r(NULL, ",", &save_ptr)) {
        uint32_t type = get_tunnel_type(token);
        if (!type) {
            VLOG_INFO("Unknown tunnel type: %s", token);
        }
        req_tunnels |= type;
    }
    free(tokstr);

    const char *hostname = smap_get_def(&cfg->external_ids, "hostname", "");
    char hostname_[HOST_NAME_MAX + 1];
    if (!hostname[0]) {
        if (gethostname(hostname_, sizeof hostname_)) {
            hostname_[0] = '\0';
        }
        hostname = hostname_;
    }

    const char *bridge_mappings = get_bridge_mappings(&cfg->external_ids);
    const char *datapath_type =
        br_int && br_int->datapath_type ? br_int->datapath_type : "";

    struct ds iface_types = DS_EMPTY_INITIALIZER;
    ds_put_cstr(&iface_types, "");
    for (int j = 0; j < cfg->n_iface_types; j++) {
        ds_put_format(&iface_types, "%s,", cfg->iface_types[j]);
    }
    ds_chomp(&iface_types, ',');
    const char *iface_types_str = ds_cstr(&iface_types);

    const struct sbrec_chassis *chassis_rec
        = get_chassis(ctx->ovnsb_idl, chassis_id);

    if (chassis_rec) {
        if (strcmp(hostname, chassis_rec->hostname)) {
            sbrec_chassis_set_hostname(chassis_rec, hostname);
        }

        /* Determine new values for Chassis external-ids. */
        const char *chassis_bridge_mappings
            = get_bridge_mappings(&chassis_rec->external_ids);
        const char *chassis_datapath_type
            = smap_get_def(&chassis_rec->external_ids, "datapath-type", "");
        const char *chassis_iface_types
            = smap_get_def(&chassis_rec->external_ids, "iface-types", "");

        /* If any of the external-ids should change, update them. */
        if (strcmp(bridge_mappings, chassis_bridge_mappings) ||
            strcmp(datapath_type, chassis_datapath_type) ||
            strcmp(iface_types_str, chassis_iface_types)) {
            struct smap new_ids;
            smap_clone(&new_ids, &chassis_rec->external_ids);
            smap_replace(&new_ids, "ovn-bridge-mappings", bridge_mappings);
            smap_replace(&new_ids, "datapath-type", datapath_type);
            smap_replace(&new_ids, "iface-types", iface_types_str);
            sbrec_chassis_verify_external_ids(chassis_rec);
            sbrec_chassis_set_external_ids(chassis_rec, &new_ids);
            smap_destroy(&new_ids);
        }

        /* Compare desired tunnels against those currently in the database. */
        uint32_t cur_tunnels = 0;
        bool same = true;
        for (int i = 0; i < chassis_rec->n_encaps; i++) {
            cur_tunnels |= get_tunnel_type(chassis_rec->encaps[i]->type);
            same = same && !strcmp(chassis_rec->encaps[i]->ip, encap_ip);

            same = same && smap_get_bool(&chassis_rec->encaps[i]->options,
                                         "csum", false);
        }
        same = same && req_tunnels == cur_tunnels;

        if (same) {
            /* Nothing changed. */
            inited = true;
            ds_destroy(&iface_types);
            return chassis_rec;
        } else if (!inited) {
            struct ds cur_encaps = DS_EMPTY_INITIALIZER;
            for (int i = 0; i < chassis_rec->n_encaps; i++) {
                ds_put_format(&cur_encaps, "%s,",
                              chassis_rec->encaps[i]->type);
            }
            ds_chomp(&cur_encaps, ',');

            VLOG_WARN("Chassis config changing on startup, make sure "
                      "multiple chassis are not configured : %s/%s->%s/%s",
                      ds_cstr(&cur_encaps),
                      chassis_rec->encaps[0]->ip,
                      encap_type, encap_ip);
            ds_destroy(&cur_encaps);
        }
    }

    ovsdb_idl_txn_add_comment(ctx->ovnsb_idl_txn,
                              "ovn-controller: registering chassis '%s'",
                              chassis_id);

    if (!chassis_rec) {
        struct smap ext_ids = SMAP_INITIALIZER(&ext_ids);
        smap_add(&ext_ids, "ovn-bridge-mappings", bridge_mappings);
        smap_add(&ext_ids, "datapath-type", datapath_type);
        smap_add(&ext_ids, "iface-types", iface_types_str);
        chassis_rec = sbrec_chassis_insert(ctx->ovnsb_idl_txn);
        sbrec_chassis_set_name(chassis_rec, chassis_id);
        sbrec_chassis_set_hostname(chassis_rec, hostname);
        sbrec_chassis_set_external_ids(chassis_rec, &ext_ids);
        smap_destroy(&ext_ids);
    }

    ds_destroy(&iface_types);
    int n_encaps = count_1bits(req_tunnels);
    struct sbrec_encap **encaps = xmalloc(n_encaps * sizeof *encaps);
    const struct smap options = SMAP_CONST1(&options, "csum", "true");

    for (int i = 0; i < n_encaps; i++) {
        const char *type = pop_tunnel_name(&req_tunnels);

        encaps[i] = sbrec_encap_insert(ctx->ovnsb_idl_txn);

        sbrec_encap_set_type(encaps[i], type);
        sbrec_encap_set_ip(encaps[i], encap_ip);
        sbrec_encap_set_options(encaps[i], &options);
    }

    sbrec_chassis_set_encaps(chassis_rec, encaps, n_encaps);
    free(encaps);

    inited = true;
    return chassis_rec;
}