Esempio n. 1
0
void
vr_mpls_exit(struct vrouter *router, bool soft_reset)
{
    unsigned int i;
    struct vr_nexthop *nh;

    if (!router->vr_max_labels || !router->vr_ilm)
        return;

    for (i = 0; i < router->vr_max_labels; i++) {
        nh = __vrouter_get_label(router, i);
        if (nh) {
            vrouter_put_nexthop(nh);
            __vrouter_set_label(router, i, NULL);
        }
    }

    if (soft_reset == false) {
        vr_btable_free(router->vr_ilm);
        router->vr_ilm = NULL;
        router->vr_max_labels = 0;
    }

    return;
}
Esempio n. 2
0
static struct vr_nexthop *
vrouter_get_label(unsigned int rid, unsigned int label)
{
    struct vrouter *router = vrouter_get(rid);

    return __vrouter_get_label(router, label);
}
Esempio n. 3
0
static void
vr_flush_entry(struct vrouter *router, struct vr_flow_entry *fe,
        struct vr_flow_md *flmd, struct vr_forwarding_md *fmd)
{
    struct vr_list_node *head;
    struct vr_packet_node *pnode;
    struct vr_packet *pkt;
    struct vr_interface *vif;

    head = fe->fe_hold_list.node_p;
    fe->fe_hold_list.node_p = NULL;

    while (head) {
        pnode = (struct vr_packet_node *)head;
        if (fmd) {
            fmd->fmd_outer_src_ip = pnode->pl_outer_src_ip;
            fmd->fmd_label = pnode->pl_label;
        }

        pkt = pnode->pl_packet;
        /* 
         * this is only a security check and not a catch all check. one note
         * of caution. please do not access pkt->vp_if till the if block is
         * succesfully bypassed
         */
        vif = __vrouter_get_interface(router, pnode->pl_vif_idx);
        if (!vif || (pkt->vp_if != vif)) {
            vr_pfree(pkt, VP_DROP_INVALID_IF);
            goto loop_continue;
        }

        if (!pkt->vp_nh) {
            if (vif_is_fabric(pkt->vp_if) && fmd &&
                    (fmd->fmd_label >= 0)) {
                pkt->vp_nh = __vrouter_get_label(router, fmd->fmd_label);
            }
        }

        vr_flow_action(router, fe, flmd->flmd_index, pkt,
                pnode->pl_proto, fmd);

loop_continue:
        head = pnode->pl_node.node_n;
        vr_free(pnode);
    }

    return;
}
Esempio n. 4
0
int
__vr_mpls_del(struct vrouter *router, unsigned int label)
{
    struct vr_nexthop *nh;

    /* hardware packet filtering (Flow Director) support */
    nh = __vrouter_get_label(router, label);
    if (nh) {
        if (vrouter_host->hos_del_mpls
            && nh->nh_type == NH_ENCAP && !(nh->nh_flags & NH_FLAG_MCAST))
            vrouter_host->hos_del_mpls(router, label);

        vrouter_put_nexthop(nh);
    }

    return __vrouter_set_label(router, label, NULL);
}
Esempio n. 5
0
int
vr_mpls_tunnel_type(unsigned int label, unsigned int control_data, unsigned
        short *reason)
{
    struct vr_nexthop *nh;
    struct vrouter *router = vrouter_get(0);
    unsigned short res;

    if (!router) {
        res = VP_DROP_MISC;
        goto fail;
    }

    label >>= VR_MPLS_LABEL_SHIFT;
    if (label >= router->vr_max_labels) {
        res = VP_DROP_INVALID_LABEL;
        goto fail;
    }

    nh = __vrouter_get_label(router, label);
    if(!nh) {
        res = VP_DROP_INVALID_NH;
        goto fail;
    }

    switch(nh->nh_family) {
    case AF_INET:
        return PKT_MPLS_TUNNEL_L3;
    case AF_BRIDGE:
        if (nh->nh_type != NH_COMPOSITE) {
            return PKT_MPLS_TUNNEL_L2_UCAST;
        }
        if (label < VR_MAX_UCAST_LABELS) {
            return PKT_MPLS_TUNNEL_L2_MCAST_EVPN;
        }
        return PKT_MPLS_TUNNEL_L2_MCAST;
    default:
        res = VP_DROP_INVALID_NH;
    }

fail:
    if (reason)
        *reason = res;
    return -1;
}
Esempio n. 6
0
int
vr_mpls_dump(vr_mpls_req *r)
{
    int ret = 0;
    unsigned int i;
    struct vr_nexthop *nh;
    struct vrouter *router = vrouter_get(r->mr_rid);
    struct vr_message_dumper *dumper = NULL;
    vr_mpls_req req;

    if (!router && (ret = -ENODEV))
        goto generate_response;

    if ((unsigned int)(r->mr_marker) + 1 >= router->vr_max_labels)
        goto generate_response;

    dumper = vr_message_dump_init(r);
    if (!dumper && (ret = -ENOMEM))
        goto generate_response;

    for (i = (unsigned int)(r->mr_marker + 1);
            i < router->vr_max_labels; i++) {
        nh = __vrouter_get_label(router, i);
        if (nh) {
           vr_mpls_make_req(&req, nh, i);
           ret = vr_message_dump_object(dumper, VR_MPLS_OBJECT_ID, &req);
           if (ret <= 0)
               break;
        }
    }

generate_response:
    vr_message_dump_exit(dumper, ret);

    return 0;
}
Esempio n. 7
0
int
vr_mpls_input(struct vrouter *router, struct vr_packet *pkt,
        struct vr_forwarding_md *fmd)
{
    int ttl, l2_offset = 0;
    unsigned int label;
    unsigned short drop_reason;

    struct vr_nexthop *nh;
    struct vr_ip *ip;
    struct vr_forwarding_md c_fmd;

    if (!fmd) {
        vr_init_forwarding_md(&c_fmd);
        fmd = &c_fmd;
    }

    label = ntohl(*(unsigned int *)pkt_data(pkt));
    ttl = label & 0xFF;
    label >>= VR_MPLS_LABEL_SHIFT;
    if (label >= router->vr_max_labels) {
        drop_reason = VP_DROP_INVALID_LABEL;
        goto dropit;
    }

    if (--ttl <= 0) {
        drop_reason = VP_DROP_TTL_EXCEEDED;
        goto dropit;
    }

    ip = (struct vr_ip *)pkt_network_header(pkt);
    fmd->fmd_outer_src_ip = ip->ip_saddr;
    vr_forwarding_md_set_label(fmd, label, VR_LABEL_TYPE_MPLS);

    /* Store the TTL in packet. Will be used for multicast replication */
    pkt->vp_ttl = ttl;

    /* drop the TOStack label */
    if (!pkt_pull(pkt, VR_MPLS_HDR_LEN)) {
        drop_reason = VP_DROP_PULL;
        goto dropit;
    }

    nh = __vrouter_get_label(router, label);
    if (!nh) {
        drop_reason = VP_DROP_INVALID_LABEL;
        goto dropit;
    }

    /*
     * Mark it for GRO. Diag, L2 and multicast nexthops unmark if
     * required
     */
    if (vr_perfr)
        pkt->vp_flags |= VP_FLAG_GRO;

    /* Reset the flags which get defined below */
    pkt->vp_flags &= ~VP_FLAG_MULTICAST;
    fmd->fmd_vlan = VLAN_ID_INVALID;

    if (nh->nh_family == AF_INET) {
        ip = (struct vr_ip *)pkt_data(pkt);
        if (vr_ip_is_ip4(ip)) {
            pkt->vp_type = VP_TYPE_IP;
        } else if (vr_ip_is_ip6(ip)) {
            pkt->vp_type = VP_TYPE_IP6;
        } else {
            drop_reason = VP_DROP_INVALID_PROTOCOL;
            goto dropit;
        }

        pkt_set_network_header(pkt, pkt->vp_data);
        pkt_set_inner_network_header(pkt, pkt->vp_data);

    } else if (nh->nh_family == AF_BRIDGE) {

        if (nh->nh_type == NH_COMPOSITE) {
            if (label >= VR_MAX_UCAST_LABELS)
                l2_offset = VR_L2_MCAST_CTRL_DATA_LEN + VR_VXLAN_HDR_LEN;
        }

        if (vr_pkt_type(pkt, l2_offset, fmd) < 0) {
            drop_reason = VP_DROP_INVALID_PACKET;
            goto dropit;
        }

    } else {
        drop_reason = VP_DROP_INVALID_NH;
        goto dropit;
    }

    /*
     * We are typically looking at interface nexthops, and hence we will
     * hit the vrf of the destination device. But, labels can also point
     * to composite nexthops (ECMP being case in point), in which case we
     * will take the vrf from the nexthop. When everything else fails, we
     * will forward the packet in the vrf in which it came i.e fabric
     */
    if (nh->nh_vrf >= 0)
        fmd->fmd_dvrf = nh->nh_vrf;
    else if (nh->nh_dev)
        fmd->fmd_dvrf = nh->nh_dev->vif_vrf;
    else
        fmd->fmd_dvrf = pkt->vp_if->vif_vrf;

    nh_output(pkt, nh, fmd);

    return 0;

dropit:
    vr_pfree(pkt, drop_reason);
    return 0;
}