Beispiel #1
0
static switch_status_t switch_api_init_default_acl_entries(
    switch_device_t device) {
  switch_acl_system_key_value_pair_t acl_kvp[5];
  switch_acl_action_params_t action_params;
  switch_acl_opt_action_params_t opt_action_params;
  switch_handle_t acl_handle;
  switch_handle_t handle;
  int priority = 100;
  switch_default_acl_t *dacl = &_switch_system_acl_data[device][0];

  memset(&opt_action_params, 0, sizeof(switch_acl_opt_action_params_t));

  // system acl for dropped packets
  dacl->acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp));
  dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_DROP;
  dacl->acl_kvp[0].value.drop_flag = 1;
  dacl->acl_kvp[0].mask.u.mask = 0xFF;
  dacl->priority = priority++;
  dacl->key_value_count = 1;
  memset(&dacl->action_params, 0, sizeof(switch_acl_action_params_t));
  dacl++;

  // port vlan mapping miss, drop
  dacl->acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp));
  dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_PORT_VLAN_MAPPING_MISS;
  dacl->acl_kvp[0].value.port_vlan_mapping_miss = 1;
  dacl->acl_kvp[0].mask.u.mask = 0xFF;
  dacl->priority = priority++;
  dacl->key_value_count = 1;
  memset(&dacl->action_params, 0, sizeof(switch_acl_action_params_t));
  dacl->action_params.drop.reason_code = DROP_PORT_VLAN_MAPPING_MISS;
  dacl++;

  // STP state == blocked, drop
  dacl->acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp));
  dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_STP_STATE;
  dacl->acl_kvp[0].value.stp_state = SWITCH_PORT_STP_STATE_BLOCKING;
  dacl->acl_kvp[0].mask.u.mask = 0xFF;
  dacl->priority = priority++;
  dacl->key_value_count = 1;
  memset(&dacl->action_params, 0, sizeof(switch_acl_action_params_t));
  dacl->action_params.drop.reason_code = DROP_STP_STATE_BLOCKING;
  dacl++;

  // STP state == learning, drop
  dacl->acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp));
  dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_STP_STATE;
  dacl->acl_kvp[0].value.stp_state = SWITCH_PORT_STP_STATE_LEARNING;
  dacl->acl_kvp[0].mask.u.mask = 0xFF;
  dacl->priority = priority++;
  dacl->key_value_count = 1;
  memset(&dacl->action_params, 0, sizeof(switch_acl_action_params_t));
  dacl->action_params.drop.reason_code = DROP_STP_STATE_LEARNING;
  dacl++;

  // ACL deny, drop
  dacl->acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp));
  dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_ACL_DENY;
  dacl->acl_kvp[0].value.acl_deny = 1;
  dacl->acl_kvp[0].mask.u.mask = 0xFF;
  dacl->priority = priority++;
  dacl->key_value_count = 1;
  memset(&dacl->action_params, 0, sizeof(switch_acl_action_params_t));
  dacl->action_params.drop.reason_code = DROP_ACL_DENY;
  dacl++;

  // URPF check fail, drop
  dacl->acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp));
  dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_URPF_CHECK;
  dacl->acl_kvp[0].value.urpf_check_fail = 1;
  dacl->acl_kvp[0].mask.u.mask = 0xFF;
  dacl->priority = priority++;
  dacl->key_value_count = 1;
  memset(&dacl->action_params, 0, sizeof(switch_acl_action_params_t));
  dacl->action_params.drop.reason_code = DROP_URPF_CHECK_FAIL;
  dacl++;

  // same if check fail, drop
  dacl->acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp));
  dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_IF_CHECK;
  dacl->acl_kvp[0].value.if_check = 0;
  dacl->acl_kvp[0].mask.u.mask = 0xFFFF;
  dacl->acl_kvp[1].field = SWITCH_ACL_SYSTEM_FIELD_BD_CHECK;
  dacl->acl_kvp[1].value.bd_check = 0;
  dacl->acl_kvp[1].mask.u.mask = 0xFFFF;
  dacl->acl_kvp[2].field = SWITCH_ACL_SYSTEM_FIELD_ROUTED;
  dacl->acl_kvp[2].value.routed = 0;
  dacl->acl_kvp[2].mask.u.mask = 0xFFFF;
  dacl->acl_kvp[3].field = SWITCH_ACL_SYSTEM_FIELD_TUNNEL_IF_CHECK;
  dacl->acl_kvp[3].value.tunnel_if_check = 0;
  dacl->acl_kvp[3].mask.u.mask = 0xFFFF;
  dacl->priority = priority++;
  dacl->key_value_count = 4;
  memset(&dacl->action_params, 0, sizeof(switch_acl_action_params_t));
  dacl->action_params.drop.reason_code = DROP_SAME_IFINDEX;
  dacl++;

  // egress ifindex is drop ifindex, drop
  dacl->acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(dacl->acl_kvp, 0, sizeof(dacl->acl_kvp));
  dacl->acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_EGRESS_IFINDEX;
  dacl->acl_kvp[0].value.out_ifindex = switch_api_drop_ifindex();
  dacl->acl_kvp[0].mask.u.mask = 0xFFFF;
  dacl->priority = priority++;
  dacl->key_value_count = 1;
  memset(&dacl->action_params, 0, sizeof(switch_acl_action_params_t));
  dacl->action_params.drop.reason_code = DROP_IFINDEX;
  dacl++;

  switch_system_acl_entries_add(device);

  // routed, ttl == 1, egress_ifindex == cpu, permit
  acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(acl_kvp, 0, sizeof(acl_kvp));
  acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_ROUTED;
  acl_kvp[0].value.routed = true;
  acl_kvp[0].mask.u.mask = 0xFF;
  acl_kvp[1].field = SWITCH_ACL_SYSTEM_FIELD_TTL;
  acl_kvp[1].value.ttl = 1;
  acl_kvp[1].mask.u.mask = 0xFF;
  acl_kvp[2].field = SWITCH_ACL_SYSTEM_FIELD_EGRESS_IFINDEX;
  acl_kvp[2].value.out_ifindex = switch_api_cpu_glean_ifindex();
  acl_kvp[2].mask.u.mask = 0xFFFF;
  memset(&action_params, 0, sizeof(switch_acl_action_params_t));
  switch_api_acl_rule_create(device,
                             acl_handle,
                             priority++,
                             3,
                             acl_kvp,
                             SWITCH_ACL_ACTION_PERMIT,
                             &action_params,
                             &opt_action_params,
                             &handle);

  // routed, ttl == 1, redirect to cpu
  acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(acl_kvp, 0, sizeof(acl_kvp));
  acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_ROUTED;
  acl_kvp[0].value.routed = true;
  acl_kvp[0].mask.u.mask = 0xFF;
  acl_kvp[1].field = SWITCH_ACL_SYSTEM_FIELD_TTL;
  acl_kvp[1].value.ttl = 1;
  acl_kvp[1].mask.u.mask = 0xFF;
  memset(&action_params, 0, sizeof(switch_acl_action_params_t));
  action_params.cpu_redirect.reason_code = SWITCH_HOSTIF_REASON_CODE_TTL_ERROR;
  switch_api_acl_rule_create(device,
                             acl_handle,
                             priority++,
                             2,
                             acl_kvp,
                             SWITCH_ACL_ACTION_REDIRECT_TO_CPU,
                             &action_params,
                             &opt_action_params,
                             &handle);

  // routed, ipv6_src_is_link_local == 1, egress_ifindex == cpu, permit
  acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(acl_kvp, 0, sizeof(acl_kvp));
  acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_ROUTED;
  acl_kvp[0].value.routed = true;
  acl_kvp[0].mask.u.mask = 0xFF;
  acl_kvp[1].field = SWITCH_ACL_SYSTEM_FIELD_LINK_LOCAL;
  acl_kvp[1].value.src_is_link_local = 1;
  acl_kvp[1].mask.u.mask = 0xFF;
  acl_kvp[2].field = SWITCH_ACL_SYSTEM_FIELD_EGRESS_IFINDEX;
  acl_kvp[2].value.out_ifindex = switch_api_cpu_glean_ifindex();
  acl_kvp[2].mask.u.mask = 0xFFFF;
  memset(&action_params, 0, sizeof(switch_acl_action_params_t));
  action_params.cpu_redirect.reason_code =
      SWITCH_HOSTIF_REASON_CODE_SRC_IS_LINK_LOCAL;
  switch_api_acl_rule_create(device,
                             acl_handle,
                             priority++,
                             3,
                             acl_kvp,
                             SWITCH_ACL_ACTION_PERMIT,
                             &action_params,
                             &opt_action_params,
                             &handle);

  // routed, ipv6_src_is_link_local == 1, redirect to cpu
  acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(acl_kvp, 0, sizeof(acl_kvp));
  acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_ROUTED;
  acl_kvp[0].value.routed = true;
  acl_kvp[0].mask.u.mask = 0xFF;
  acl_kvp[1].field = SWITCH_ACL_SYSTEM_FIELD_LINK_LOCAL;
  acl_kvp[1].value.src_is_link_local = 1;
  acl_kvp[1].mask.u.mask = 0xFF;
  memset(&action_params, 0, sizeof(switch_acl_action_params_t));
  action_params.cpu_redirect.reason_code =
      SWITCH_HOSTIF_REASON_CODE_SRC_IS_LINK_LOCAL;
  switch_api_acl_rule_create(device,
                             acl_handle,
                             priority++,
                             2,
                             acl_kvp,
                             SWITCH_ACL_ACTION_REDIRECT_TO_CPU,
                             &action_params,
                             &opt_action_params,
                             &handle);

  // routed, ingress bd == egress bd, copy to cpu
  acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(acl_kvp, 0, sizeof(acl_kvp));
  acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_ROUTED;
  acl_kvp[0].value.routed = true;
  acl_kvp[0].mask.u.mask = 0xFF;
  acl_kvp[1].field = SWITCH_ACL_SYSTEM_FIELD_BD_CHECK;
  acl_kvp[1].value.bd_check = 0;
  acl_kvp[1].mask.u.mask = 0xFFFF;
  memset(&action_params, 0, sizeof(switch_acl_action_params_t));
  action_params.cpu_redirect.reason_code =
      SWITCH_HOSTIF_REASON_CODE_ICMP_REDIRECT;
  switch_api_acl_rule_create(device,
                             acl_handle,
                             priority++,
                             2,
                             acl_kvp,
                             SWITCH_ACL_ACTION_COPY_TO_CPU,
                             &action_params,
                             &opt_action_params,
                             &handle);

  // l3_copy to cpu
  acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_INGRESS, SWITCH_ACL_TYPE_SYSTEM);
  memset(acl_kvp, 0, sizeof(acl_kvp));
  acl_kvp[0].field = SWITCH_ACL_SYSTEM_FIELD_L3_COPY;
  acl_kvp[0].value.l3_copy = true;
  acl_kvp[0].mask.u.mask = 0xFF;
  memset(&action_params, 0, sizeof(switch_acl_action_params_t));
  switch_api_acl_rule_create(device,
                             acl_handle,
                             priority++,
                             1,
                             acl_kvp,
                             SWITCH_ACL_ACTION_COPY_TO_CPU,
                             &action_params,
                             &opt_action_params,
                             &handle);

  switch_default_acl_t *egr_acl = &_switch_egress_acl_data[device][0];
  // set acl handler and priority for egress mtu check rule
  egr_acl->acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_EGRESS, SWITCH_ACL_TYPE_EGRESS_SYSTEM);
  egr_acl->priority = priority++;
  egr_acl->key_value_count = 1;
  switch_api_acl_reference(device, egr_acl->acl_handle, 0);
  egr_acl++;

  // set acl handler and priority for egress dod rule
  egr_acl->acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_EGRESS, SWITCH_ACL_TYPE_EGRESS_SYSTEM);
  egr_acl->priority = priority++;
  egr_acl->key_value_count = 1;
  switch_api_acl_reference(device, egr_acl->acl_handle, 0);
  egr_acl++;

  egr_acl->acl_handle = switch_api_acl_list_create(
      device, SWITCH_API_DIRECTION_EGRESS, SWITCH_ACL_TYPE_EGRESS_SYSTEM);
  egr_acl->priority = priority++;
  egr_acl->key_value_count = 1;
  switch_api_acl_reference(device, egr_acl->acl_handle, 0);

  switch_egress_acl_entries_add(device);

  return SWITCH_STATUS_SUCCESS;
}
switch_status_t
switch_nhop_ifindex_get(switch_handle_t nhop_handle,
                        switch_ifindex_t *ifindex,
                        bool *flood,
                        uint32_t *mc_index)
{
    switch_nhop_info_t                *nhop_info = NULL;
    switch_interface_info_t           *intf_info = NULL;
    switch_neighbor_info_t            *neighbor_info = NULL;
    switch_api_neighbor_t             *neighbor = NULL;
    switch_api_mac_entry_t             mac_entry;
    switch_mac_info_t                 *mac_info = NULL;
    switch_handle_t                    neighbor_handle;
    switch_bd_info_t                  *bd_info = NULL;
    switch_port_info_t                *tmp_port_info = NULL;
    switch_lag_info_t                 *tmp_lag_info = NULL;
    switch_interface_info_t           *tmp_intf_info = NULL;
    switch_api_mac_entry_t            *tmp_mac_entry = NULL;
    switch_handle_type_t               handle_type = 0;
    switch_handle_t                    encap_if;
    switch_spath_info_t               *spath_info = NULL;

    nhop_info = switch_nhop_get(nhop_handle);
    if (!nhop_info) {
        return SWITCH_STATUS_INVALID_HANDLE;
    }

    spath_info = &(SWITCH_NHOP_SPATH_INFO(nhop_info));
    intf_info = switch_api_interface_get(spath_info->nhop_key.intf_handle);
    if (!intf_info) {
        return SWITCH_STATUS_INVALID_HANDLE;
    }

    *ifindex = intf_info->ifindex;
    *flood = FALSE;
    *mc_index = 0;

    if (SWITCH_INTF_TYPE(intf_info) == SWITCH_API_INTERFACE_TUNNEL) {
        encap_if = SWITCH_INTF_TUNNEL_ENCAP_OUT_IF(intf_info);
        intf_info = switch_api_interface_get(encap_if);
        if (!intf_info) {
            return SWITCH_STATUS_INVALID_HANDLE;
        }
        *ifindex = intf_info->ifindex;
        SWITCH_API_TRACE("%s:%d ifindex for tunnel interface: %x",
                         __FUNCTION__, __LINE__, *ifindex);
    }

    if (SWITCH_INTF_TYPE(intf_info) == SWITCH_API_INTERFACE_L3_VLAN) {
        neighbor_handle = spath_info->neighbor_handle;
        if (neighbor_handle == SWITCH_API_INVALID_HANDLE ||
            neighbor_handle == 0) {
            *ifindex = switch_api_cpu_glean_ifindex();
        } else {
            neighbor_info = switch_neighbor_info_get(neighbor_handle);
            if (!neighbor_info) {
                return SWITCH_STATUS_INVALID_HANDLE;
            }
            neighbor = &neighbor_info->neighbor;
            memset(&mac_entry, 0, sizeof(switch_api_mac_entry_t));
            mac_entry.vlan_handle = intf_info->bd_handle;
            memcpy(&mac_entry.mac, &neighbor->mac_addr, ETH_LEN);
            mac_info = switch_mac_table_entry_find(&mac_entry);
            if (!mac_info) {
                bd_info = switch_bd_get(intf_info->bd_handle);
                if (!bd_info) {
                    return SWITCH_STATUS_INVALID_HANDLE;
                }
                *mc_index = handle_to_id(bd_info->uuc_mc_index);
                *flood = TRUE;
            } else {
                tmp_mac_entry = &mac_info->mac_entry;
                handle_type = switch_handle_get_type(tmp_mac_entry->handle);
                switch (handle_type) {
                    case SWITCH_HANDLE_TYPE_PORT:
                        tmp_port_info = switch_api_port_get_internal(tmp_mac_entry->handle);
                        if (!tmp_port_info) {
                            return SWITCH_STATUS_INVALID_HANDLE;
                        }
                        *ifindex = tmp_port_info->ifindex;
                        break;
                    case SWITCH_HANDLE_TYPE_LAG:
                        tmp_lag_info = switch_api_lag_get_internal(tmp_mac_entry->handle);
                        if (!tmp_lag_info) {
                            return SWITCH_STATUS_INVALID_HANDLE;
                        }
                        *ifindex = tmp_lag_info->ifindex;
                        break;
                    case SWITCH_HANDLE_TYPE_INTERFACE:
                        tmp_intf_info = switch_api_interface_get(tmp_mac_entry->handle);
                        if (!tmp_intf_info) {
                            return SWITCH_STATUS_INVALID_HANDLE;
                        }
                        *ifindex = tmp_intf_info->ifindex;
                        break;
                    default:
                        return SWITCH_STATUS_INVALID_HANDLE;
                }
            }
        }
    }
    return SWITCH_STATUS_SUCCESS;
}