当前位置: 首页 > 工具软件 > XORP > 使用案例 >

xorp与click通信分析

葛宪
2023-12-01

XORP中的FibConfigTableSetClick::start(string& error_msg)方法开始向CLICK推送转发表

int
FibConfigTableSetClick::start(string& error_msg)
{
    if (! ClickSocket::is_enabled())//首先,在xorp中配置好click后,启动xorp之后便会在13000端口上与click建立连接,click是SOCKET的服务端,XORP是作为客户端去连接的
    return (XORP_OK);

    if (_is_running)
    return (XORP_OK);

    if (ClickSocket::start(error_msg) != XORP_OK)//xorp/fea/data_plane/control_socket/click_socket.cc:user-level上,启动click,并建立与click的socket连接,这个启动过程会读取config.boot里的参数
    return (XORP_ERROR);

    // Cleanup any leftover entries from previously run XORP instance
    if (! fibconfig().unicast_forwarding_entries_retain_on_startup4())
    delete_all_entries4();
    if (! fibconfig().unicast_forwarding_entries_retain_on_startup6())
    delete_all_entries6();

    _is_running = true;

    //
    // XXX: Push the current config into the new method
    //
    list<Fte4> fte_list4;
    if (fibconfig().get_table4(fte_list4) == XORP_OK) {
    if (set_table4(fte_list4) != XORP_OK) {
        XLOG_ERROR("Cannot push the current IPv4 forwarding table "
               "into the FibConfigTableSetClick plugin for setting "
               "the forwarding table");
    }
    }

#ifdef HAVE_IPV6
    list<Fte6> fte_list6;
    if (fibconfig().get_table6(fte_list6) == XORP_OK) {
    if (set_table6(fte_list6) != XORP_OK) {
        XLOG_ERROR("Cannot push the current IPv6 forwarding table "
               "into the FibConfigTableSetClick plugin for setting "
               "the forwarding table");
    }
    }
#endif // HAVE_IPV6

    return (XORP_OK);
}

所以项目中click主动向xorp汇报接口信息要改的东西就很多很多了,XORP与CLICK的配合前提是在配置文件里事先写好了所有接口信息

附:这段代码启动user-level click,并与之建立socket,为上述函数做准备

int
ClickSocket::start(string& error_msg)
{
    if (is_kernel_click() && !_kernel_fd.is_valid()) {
    //
    // Install kernel Click (if necessary)
    //
    if (_kernel_click_install_on_startup) {
        string error_msg2;

        // Load the kernel Click modules
        if (load_kernel_click_modules(error_msg) != XORP_OK) {
        unload_kernel_click_modules(error_msg2);
        return (XORP_ERROR);
        }

        // Mount the Click file system
        if (mount_click_file_system(error_msg) != XORP_OK) {
        unload_kernel_click_modules(error_msg2);
        return (XORP_ERROR);
        }
    }

#ifdef O_NONBLOCK
    //
    // Open the Click error file (for reading error messages)
    //
    string click_error_filename;
    click_error_filename = _kernel_click_mount_directory + "/errors";
    _kernel_fd = open(click_error_filename.c_str(), O_RDONLY | O_NONBLOCK);
    if (!_kernel_fd.is_valid()) {
        error_msg = c_format("Cannot open kernel Click error file %s: %s",
                 click_error_filename.c_str(),
                 strerror(errno));
        return (XORP_ERROR);
    }
#endif
    }

    if (is_user_click() && !_user_fd.is_valid()) {
    //
    // Execute the Click command (if necessary)
    //
    if (_user_click_command_execute_on_startup) {
        // Compose the command and the arguments
        string command = _user_click_command_file;
        list<string> argument_list;
        argument_list.push_back("-f");
        argument_list.push_back(_user_click_startup_config_file);
        argument_list.push_back("-p");
        argument_list.push_back(c_format("%u",
                     _user_click_control_socket_port));
        if (! _user_click_command_extra_arguments.empty()) {
        list<string> l = split(_user_click_command_extra_arguments,
                       ' ');
        argument_list.insert(argument_list.end(), l.begin(), l.end());
        }

        if (execute_user_click_command(command, argument_list)
        != XORP_OK) {
        error_msg = c_format("Could not execute the user-level Click");
        return (XORP_ERROR);
        }
    }

    //
    // Open the socket
    //
    struct in_addr in_addr;
    _user_click_control_address.copy_out(in_addr);
    //
    // TODO: XXX: get rid of this hackish mechanism of waiting
    // pre-defined amount of time until the user-level Click program
    // starts responding.
    //
    TimeVal max_wait_time = USER_CLICK_STARTUP_MAX_WAIT_TIME;
    TimeVal curr_wait_time(0, 100000);    // XXX: 100ms
    TimeVal total_wait_time;
    do {
        //
        // XXX: try-and-wait a number of times up to "max_wait_time",
        // because the user-level Click program may not response
        // immediately.
        //
        TimerList::system_sleep(curr_wait_time);
        total_wait_time += curr_wait_time;
        int in_progress = 0;
        _user_fd = comm_connect_tcp4(&in_addr,
                     htons(_user_click_control_socket_port),
                     COMM_SOCK_BLOCKING, &in_progress);
        if (_user_fd.is_valid())
        break;
        if (total_wait_time < max_wait_time) {
        // XXX: exponentially increase the wait time
        curr_wait_time += curr_wait_time;
        if (total_wait_time + curr_wait_time > max_wait_time)
            curr_wait_time = max_wait_time - total_wait_time;
        XLOG_WARNING("Could not open user-level Click socket: %s. "
                 "Trying again...",
                 strerror(errno));
        continue;
        }
        error_msg = c_format("Could not open user-level Click socket: %s",
                 strerror(errno));
        terminate_user_click_command();
        return (XORP_ERROR);
    } while (true);

    //
    // Read the expected banner
    //
    vector<uint8_t> message;
    string error_msg2;
    if (force_read_message(_user_fd, message, error_msg2) != XORP_OK) {
        error_msg = c_format("Could not read on startup from user-level "
                 "Click socket: %s", error_msg2.c_str());
        terminate_user_click_command();
        comm_close(_user_fd);
        _user_fd.clear();
        return (XORP_ERROR);
    }

    //
    // Check the expected banner.
    // The banner should look like: "Click::ControlSocket/1.1"
    //
    do {
        string::size_type slash1, slash2, dot1, dot2;
        string banner = string(reinterpret_cast<const char*>(&message[0]),
                   message.size());
        string version;
        int major, minor;

        // Find the version number and check it.
        slash1 = banner.find('/');
        if (slash1 == string::npos) {
        error_msg = c_format("Invalid user-level Click banner: %s",
                     banner.c_str());
        goto error_label;
        }
        slash2 = banner.find('/', slash1 + 1);
        if (slash2 != string::npos)
        version = banner.substr(slash1 + 1, slash2 - slash1 - 1);
        else
        version = banner.substr(slash1 + 1);

        dot1 = version.find('.');
        if (dot1 == string::npos) {
        error_msg = c_format("Invalid user-level Click version: %s",
                     version.c_str());
        goto error_label;
        }
        dot2 = version.find('.', dot1 + 1);
        major = atoi(version.substr(0, dot1).c_str());
        if (dot2 != string::npos)
        minor = atoi(version.substr(dot1 + 1, dot2 - dot1 - 1).c_str());
        else
        minor = atoi(version.substr(dot1 + 1).c_str());
        if ((major < CLICK_MAJOR_VERSION)
        || ((major == CLICK_MAJOR_VERSION)
            && (minor < CLICK_MINOR_VERSION))) {
        error_msg = c_format("Invalid user-level Click version: "
                     "expected at least %d.%d "
                     "(found %s)",
               CLICK_MAJOR_VERSION, CLICK_MINOR_VERSION,
               version.c_str());
        goto error_label;
        }
        break;

    error_label:
        terminate_user_click_command();
        comm_close(_user_fd);
        _user_fd.clear();
        return (XORP_ERROR);
    } while (false);

    //
    // Add the socket to the event loop
    //
    if (_eventloop.add_ioevent_cb(_user_fd, IOT_READ,
                    callback(this, &ClickSocket::io_event))
        == false) {
        error_msg = c_format("Failed to add user-level Click socket "
                 "to EventLoop");
        terminate_user_click_command();
        comm_close(_user_fd);
        _user_fd.clear();
        return (XORP_ERROR);
    }
    }

    return (XORP_OK);
}

转载于:https://www.cnblogs.com/yangyh/archive/2010/09/07/1821034.html

 类似资料: