Example #1
0
unsigned int
vr_fabric_input(struct vr_interface *vif, struct vr_packet *pkt,
                unsigned short vlan_id)
{
    int handled = 0;
    unsigned short pull_len;
    struct vr_forwarding_md fmd;

    vr_init_forwarding_md(&fmd);
    fmd.fmd_vlan = vlan_id;
    fmd.fmd_dvrf = vif->vif_vrf;

    if (vr_pkt_type(pkt, 0, &fmd) < 0) {
        vif_drop_pkt(vif, pkt, 1);
        return 0;
    }

    if (pkt->vp_type == VP_TYPE_IP6)
        return vif_xconnect(vif, pkt, &fmd);

    pull_len = pkt_get_network_header_off(pkt) - pkt_head_space(pkt);
    pkt_pull(pkt, pull_len);

    if (pkt->vp_type == VP_TYPE_IP || pkt->vp_type == VP_TYPE_IP6)
        handled = vr_l3_input(pkt, &fmd);
    else if (pkt->vp_type == VP_TYPE_ARP)
        handled = vr_arp_input(pkt, &fmd);

    if (!handled) {
        pkt_push(pkt, pull_len);
        return vif_xconnect(vif, pkt, &fmd);
    }

    return 0;
}
Example #2
0
unsigned int
vr_reinject_packet(struct vr_packet *pkt, struct vr_forwarding_md *fmd)
{
    struct vr_interface *vif = pkt->vp_if;
    int handled;

    if (pkt->vp_nh) {
        /* If nexthop does not have valid data, drop it */
        if (!(pkt->vp_nh->nh_flags & NH_FLAG_VALID)) {
            vr_pfree(pkt, VP_DROP_INVALID_NH);
            return 0;
        }

        return pkt->vp_nh->nh_reach_nh(pkt, pkt->vp_nh, fmd);
    }

    if (vif_is_vhost(vif)) {
        handled = vr_l3_input(pkt, fmd);
        if (!handled)
            vif_drop_pkt(vif, pkt, 1);
        return 0;
    }


    return vr_bridge_input(vif->vif_router, pkt, fmd);
}
/*
 * vr_interface_input() is invoked if a packet ingresses an interface. 
 * This function demultiplexes the packet to right input 
 * function depending on the protocols enabled on the VIF
 */
static unsigned int
vr_interface_input(unsigned short vrf, struct vr_interface *vif,
                       struct vr_packet *pkt, unsigned short vlan_id)
{
    struct vr_forwarding_md fmd;
    unsigned int ret;

    vr_init_forwarding_md(&fmd);

    if (vif->vif_flags & VIF_FLAG_MIRROR_RX) {
        fmd.fmd_dvrf = vif->vif_vrf;
        vr_mirror(vif->vif_router, vif->vif_mirror_id, pkt, &fmd);
    }

    /* If vlan tagged from VM, packet needs to be treated as L2 packet */
    if ((vif->vif_type == VIF_TYPE_PHYSICAL) ||  (vlan_id == VLAN_ID_INVALID)) {
        if (vif->vif_flags & VIF_FLAG_L3_ENABLED) {
            ret = vr_l3_input(vrf, pkt, &fmd);
            if (ret != PKT_RET_FALLBACK_BRIDGING)
                return ret;
        }
    }

    if (vif->vif_flags & VIF_FLAG_L2_ENABLED)
        return vr_l2_input(vrf, pkt, &fmd, vlan_id);

    vif_drop_pkt(vif, pkt, 1);
    return 0;
}
Example #4
0
/*
 * vr_interface_input() is invoked if a packet ingresses an interface.
 * This function demultiplexes the packet to right input
 * function depending on the protocols enabled on the VIF
 */
unsigned int
vr_virtual_input(unsigned short vrf, struct vr_interface *vif,
                 struct vr_packet *pkt, unsigned short vlan_id)
{
    struct vr_forwarding_md fmd;

    vr_init_forwarding_md(&fmd);
    fmd.fmd_vlan = vlan_id;
    fmd.fmd_dvrf = vrf;

    if (vif->vif_flags & VIF_FLAG_MIRROR_RX) {
        fmd.fmd_dvrf = vif->vif_vrf;
        vr_mirror(vif->vif_router, vif->vif_mirror_id, pkt, &fmd);
    }

    if (vr_pkt_type(pkt, 0, &fmd) < 0) {
        vif_drop_pkt(vif, pkt, 1);
        return 0;
    }

    /*
     * we really do not allow any broadcast packets from interfaces
     * that are part of transparent service chain, since transparent
     * service chain bridges packets across vrf (and hence loops can
     * happen)
     */
    if ((pkt->vp_flags & VP_FLAG_MULTICAST) &&
            (vif_is_service(vif))) {
        vif_drop_pkt(vif, pkt, 1);
        return 0;
    }

    if (!vr_flow_forward(pkt->vp_if->vif_router, pkt, &fmd))
        return 0;

    vr_bridge_input(vif->vif_router, pkt, &fmd);
    return 0;

}
Example #5
0
int
vif_xconnect(struct vr_interface *vif, struct vr_packet *pkt)
{
    struct vr_interface *bridge;
    
    if (!vif)
        goto free_pkt;

    bridge = vif->vif_bridge;
    if (bridge) {
        vr_preset(pkt);
        return bridge->vif_tx(bridge, pkt);
    }

free_pkt:
    if (vif)
        vif_drop_pkt(vif, pkt, 1);
    return 0;
}
/*
 * vr_input is called from linux(host) ingress path. we are not allowed to
 * sleep here. return value should indicate whether the router consumed the
 * packet or not. if the router did not consume, host will continue with
 * its packet processing with the same packet. if the router did consume,
 * host will not touch the packet again. a return of 0 will tell the handler
 * that router consumed it, while all other return values are passed as is.
 * maybe we need a return value to host return mapping, but at a later time ?
 */
unsigned int
vr_input(unsigned short vrf, struct vr_interface *vif, struct vr_packet *pkt)
{
    unsigned char *data = pkt_data(pkt);
    unsigned char *eth = data;
    unsigned char *dmac = &eth[VR_ETHER_DMAC_OFF];
    unsigned short eth_proto;
    struct vr_vlan_hdr *vlan;
    struct vrouter *router = vif->vif_router;
    struct vr_forwarding_md fmd;
    int reason;

    if (vif->vif_flags & VIF_FLAG_MIRROR_RX) {
        vr_init_forwarding_md(&fmd);
        fmd.fmd_dvrf = vif->vif_vrf;
        vr_mirror(vif->vif_router, vif->vif_mirror_id, pkt, &fmd);
    }

    /*
     * we will optimise for the most likely case i.e that of IPv4. need
     * to see what needs to happen for v6 when it comes
     */
    data = pkt_pull(pkt, VR_ETHER_HLEN);
    if (!data) {
        vif_drop_pkt(vif, pkt, 1);
        return 0;
    }

    eth_proto = ntohs(*(unsigned short *)(eth + VR_ETHER_PROTO_OFF));
    while (eth_proto == VR_ETH_PROTO_VLAN) {
        vlan = (struct vr_vlan_hdr *)data;
        eth_proto = ntohs(vlan->vlan_proto);
        data = pkt_pull(pkt, sizeof(*vlan));
        if (!data) {
            vif_drop_pkt(vif, pkt, 1);
            return 0;
        }
    }

    vr_init_forwarding_md(&fmd);

    pkt_set_network_header(pkt, pkt->vp_data);
    pkt_set_inner_network_header(pkt, pkt->vp_data);
    if (eth_proto == VR_ETH_PROTO_IP) {
        if (vr_from_vm_mss_adj && vr_pkt_from_vm_tcp_mss_adj &&
                         (vif->vif_type == VIF_TYPE_VIRTUAL)) {
            if ((reason = vr_pkt_from_vm_tcp_mss_adj(pkt))) {
                vr_pfree(pkt, reason);
                return 0;
            }
        }

        return vr_flow_inet_input(router, vrf, pkt, eth_proto, &fmd);
    } else if (eth_proto == VR_ETH_PROTO_ARP)
        return vr_arp_input(router, vrf, pkt);

    /* rest of the stuff is for slow path and we should be ok doing this */
    if (well_known_mac(dmac))
        return vr_trap(pkt, vrf,  AGENT_TRAP_L2_PROTOCOLS, NULL);


    return vr_default_input(pkt);
}