Processing the Configuration

This page discusses configuration processing in the management component and in the control component.

Loading the Configuration in the Management Component

The management component must parse, validate and load the configuration hierarchy introduced in System Configuration for the Dynamic Policy Manager Application. These actions are triggered by a configured change. Because the control component might not be available and connected when the change is committed, the management component stores a record of the configuration to ensure sending accurate information to the control component.

When the system's configuration is found and examined for validity, the entire new configuration replaces the one previously stored (if any). While it is possible to extract the configuration changes, this example avoids taking that approach for simplicity.

When the configuration is successfully stored into the management component's memory, and when or if the control component is connected, the management component pushes the entire new configuration to the control component. The control component also handles the configuration in this 'reset' fashion.

The management component traces messages as it loads the configuration to observe and understand progress; the effects of the configuration might not appear immediately. Configuring traceoptions enables this supplementary debug and informational logging to the configured trace file.

Logging is performed through syslog at the external facility and at the informational level. The DPM-MGMT log tag is used so that messages from this system can easily be filtered for viewing.

Receiving the Configuration in the Control Component

At the beginning and end of a configuration update, the management component sends start and end messages to the control component. During the configuration change, subscriber interaction through the web portal is suspended.

The configuration information comes in the form of messages. When the control component first receives the start message, it purges all previous policies that the application has applied (this example takes this approach to simplify the code). Consequently, subscriber logins are not persistent across configuration changes, but these changes are expected to be very infrequent. This purge also takes place upon any loss of communication with the management component, such as when the management component is shut down.

Processing the Configuration in the Control Component

The application's control component processes the policy configuration in two places:

The application must be able to handle the dynamic changes quickly, because they can occur frequently.

The control application works as follows:

Applying Default Policies

As configuration update messages are received, the application begins applying the default interface policies for all the interfaces under management. As the list of managed interfaces is received, an input and output filter that matches all traffic to each of these interfaces is applied. The corresponding action is a policer supplied to match the input or output direction.

At this point the application is said to be statically set up, and is ready to interact dynamically with subscriber login requests. This is done through a web portal set up by the application and expected to run concurrently in the control component.

The API structures junos_dfw_policer_info_t, junos_dfw_filter_info_t, junos_dfw_term_info_t, and junos_dfw_filter_attach_info_t are used to supply all the data about the filters, policers, and interface attach points. The code for this is in the function apply_default_int_policy(), in the file dpm-ctrl_dfw.c.

The code fills in the structures with the values from the configuration, in some cases using constants provided by the API, and creates the filter add transaction by calling junos_dfw_filter_trans_alloc() and passing the constant JUNOS_DFW_FILTER_OP_ADD.

It then adds terms by calling junos_dfw_term_start(). In this call:

You can define the filter terms as JUNOS_DFW_TERM_TYPE_ORDERED (terms are matched in the order provided during configuration,) or JUNOS_DFW_TERM_TYPE_PRIORITISED (terms are matched according to the match algorithm,) depending on the type of filter you are configuring. The operations you can perform are JUNOS_DFW_TERM_OP_ADD, JUNOS_DFW_TERM_OP_DELETE, and JUNOS_DFW_TERM_OP_REPLACE.

The following code adds the terms in the namestr_key strings for the ingress and egress directions. i_trans_hdl is the filter handle, and i_dti and e_dti point to the structures containing the input and output terms.

junos_dfw_term_info_t i_dti, e_dti;  

...

    strlcpy(i_dti.namestr_key, sub_name, sizeof(i_dti.namestr_key));
    i_dti.type = JUNOS_DFW_TERM_TYPE_ORDERED;
    i_dti.property.order.term_adj_type = JUNOS_DFW_TERM_ADJ_PREV;
    // if we specify prev and dti.property.order.term_adj_namestr_key is empty
    // like this, then this term that we are adding becomes first in the filter

    bzero(&e_dti, sizeof(e_dti));
    strlcpy(e_dti.namestr_key, sub_name, sizeof(e_dti.namestr_key));
    e_dti.type = JUNOS_DFW_TERM_TYPE_ORDERED;
    e_dti.property.order.term_adj_type = JUNOS_DFW_TERM_ADJ_PREV;
    // if we specify prev and dti.property.order.term_adj_namestr_key is empty
    // like this, then this term that we are adding becomes first in the filter
    
    if(junos_dfw_term_start(i_trans_hdl, &i_dti, JUNOS_DFW_TERM_OP_ADD)) {
        LOG(LOG_ERR, "%s: junos_dfw_term_start failed (i)", __func__);
        goto failed;
    }
    if(junos_dfw_term_start(e_trans_hdl, &e_dti, JUNOS_DFW_TERM_OP_ADD)) {
        LOG(LOG_ERR, "%s: junos_dfw_term_start failed (e)", __func__);
        goto failed;
    }

The application then specifies actions for input and output policers. junos_dfw_term_action_policer() is called to apply limits to the traffic using the policer referenced by dpi.

    // Specify term action as the policer for this subscriber
    
    if(junos_dfw_term_action_policer(i_trans_hdl, &dpi)) {
        LOG(LOG_ERR, "%s: junos_dfw_term_action_policer failed (i)",
                __func__);
        goto failed;
    }
    if(junos_dfw_term_action_policer(e_trans_hdl, &dpi)) {
        LOG(LOG_ERR, "%s: junos_dfw_term_action_policer failed (e)",
                __func__);
        goto failed;
    }
    
    if(junos_dfw_term_end(i_trans_hdl) < 0) {
        LOG(LOG_ERR, "%s: junos_dfw_term_end failed (i)", __func__);
        goto failed;
    }
    if(junos_dfw_term_end(e_trans_hdl) < 0) {
        LOG(LOG_ERR, "%s: junos_dfw_term_end failed (e)", __func__);
        goto failed;
    }

The application calls junos_dfw_trans_send() to add the filters:

    if(junos_dfw_trans_send(dfw_handle, i_trans_hdl, dpm_cid, 0)) {
        LOG(LOG_ERR, "%s: junos_dfw_trans_send failed (i)", __func__);
        goto failed;
    }
    if(junos_dfw_trans_send(dfw_handle, e_trans_hdl, dpm_cid, 0)) {
        LOG(LOG_ERR, "%s: junos_dfw_trans_send failed (e)", __func__);
        goto failed;
    }

Finally, the filters are applied to the interface using attach points, which contain the input or output interface information. Attaching a filter requires its own transaction, which you create by calling junos_dfw_filter_attach_trans_alloc() to allocate an attach transaction handle, followed by junos_dfw_trans_send():

     junos_dfw_filter_attach_info_t dfai;

...

    dfai.attach_point = JUNOS_DFW_FILTER_ATTACH_POINT_INPUT_INTF;
    strlcpy(dfai.type.intf.ifd_name, int_name, sizeof(dfai.type.intf.ifd_name));
    tmp = dfai.type.intf.ifd_name;
    strsep(&tmp, "."); // replace '.' with a '\0'
    dfai.type.intf.sub_unit = strtol(strstr(int_name, ".") + 1  , (char **)NULL,10);
    
    // Ingress side
    
    if(junos_dfw_filter_attach_trans_alloc(&i_filter_info, &dfai,&i_trans_hdl)){
        LOG(LOG_ERR, "%s: junos_dfw_filter_attach_trans_alloc failed (i)",
                __func__);
        goto failed;
    }
    if(junos_dfw_trans_send(dfw_handle, i_trans_hdl, dpm_cid, 0)) {
        LOG(LOG_ERR, "%s: junos_dfw_trans_send (attach) failed (i)",
                __func__);
        goto failed;
    }
    
    // Egress side
    
    dfai.attach_point = JUNOS_DFW_FILTER_ATTACH_POINT_OUTPUT_INTF;

    if(junos_dfw_filter_attach_trans_alloc(&e_filter_info, &dfai,&e_trans_hdl)){
        LOG(LOG_ERR, "%s: junos_dfw_filter_attach_trans_alloc failed (e)",
                __func__);
        goto failed;
    }
    if(junos_dfw_trans_send(dfw_handle, e_trans_hdl, dpm_cid, 0)) {
        LOG(LOG_ERR, "%s: junos_dfw_trans_send (attach) failed (e)",
                __func__);
        goto failed;
    }
    
failed: // or done
    junos_dfw_trans_handle_free(i_trans_hdl);
    junos_dfw_trans_handle_free(e_trans_hdl);
}

Applying Dynamic Policers


2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:26:47 2010 for Juniper Networks Partner Solution Development Platform JUNOS SDK 10.2R1 by Doxygen 1.4.5