zoukankan      html  css  js  c++  java
  • xorp与click通信分析

    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);
    }

  • 相关阅读:
    深入理解Java中的final关键字
    【事故处理】开车撞了人,一定要这样处理,否则后悔终生!
    spark、storm与Hadoop
    深入理解Java中的final关键字
    java并发之原子性、可见性、有序性
    java中重写equals和hashCode方法
    RESTClient插件POST方法传递参数
    Java内部类的作用
    java常用设计模式
    思辨: 讨论交流和独立思考谁更重要。
  • 原文地址:https://www.cnblogs.com/yangyh/p/1821034.html
Copyright © 2011-2022 走看看