Esempio n. 1
0
/* Delete port to the bridge. */
lagopus_result_t
bridge_port_delete(struct bridge_list *bridge_list, const char *name,
                   uint32_t portid) {
  struct bridge *bridge;
  struct port *port;
  lagopus_result_t ret;

  flowdb_wrlock(NULL);
  /* Lookup bridge by name. */
  bridge = bridge_lookup(bridge_list, name);
  if (bridge != NULL) {
    port = ifindex2port(bridge->ports, portid);
    if (port != NULL && port->bridge == bridge) {
      printf("Release port id %u from bridge %s\n",
             port->ifindex, bridge->name);
      vector_set_index(bridge->ports, port->ofp_port.port_no, NULL);
      send_port_status(port, OFPPR_DELETE);
      port->bridge = NULL;
      ret = LAGOPUS_RESULT_OK;
    } else {
      ret = LAGOPUS_RESULT_NOT_FOUND;
    }
  } else {
    ret = LAGOPUS_RESULT_NOT_FOUND;
  }

  flowdb_wrunlock(NULL);
  return ret;
}
Esempio n. 2
0
/* Add a new bridge. */
lagopus_result_t
bridge_add(struct bridge_list *bridge_list, const char *name, uint64_t dpid) {
  struct bridge *bridge;

  /* Find bridge. */
  bridge = bridge_lookup(bridge_list, name);
  if (bridge != NULL) {
    return LAGOPUS_RESULT_ALREADY_EXISTS;
  }

  /* Allocate a new bridge. */
  bridge = bridge_alloc(name);
  if (bridge == NULL) {
    return LAGOPUS_RESULT_NO_MEMORY;
  }

  /* If given dpid is zero, generate random dpid value. */
  if (dpid == 0) {
    dpid = bridge_dpid_generate();
  }
  bridge->dpid = dpid;

  flowdb_wrlock(NULL);
  TAILQ_INSERT_TAIL(bridge_list, bridge, entry);
  flowdb_wrunlock(NULL);

  lagopus_msg_info("Bridge %s dpid:%0" PRIx64 " is added\n", name, dpid);
  return LAGOPUS_RESULT_OK;
}
Esempio n. 3
0
/* Set bridge dpid. */
lagopus_result_t
dpmgr_bridge_dpid_set(struct dpmgr *dpmgr,
                      const char *bridge_name,
                      uint64_t dpid) {
  struct bridge *bridge;
  lagopus_result_t rv;

  FLOWDB_RWLOCK_WRLOCK(NULL);
  bridge = bridge_lookup(&dpmgr->bridge_list, bridge_name);
  if (bridge != NULL) {
    bridge->dpid = dpid;
    rv = LAGOPUS_RESULT_OK;
  } else {
    rv = LAGOPUS_RESULT_NOT_FOUND;
  }
  FLOWDB_RWLOCK_WRUNLOCK(NULL);
  return rv;
}
Esempio n. 4
0
/* Delete bridge. */
lagopus_result_t
bridge_delete(struct bridge_list *bridge_list, const char *name) {
  struct bridge *bridge;
  lagopus_result_t ret;

  flowdb_wrlock(NULL);
  /* Lookup bridge by name. */
  bridge = bridge_lookup(bridge_list, name);
  if (bridge != NULL) {
    TAILQ_REMOVE(bridge_list, bridge, entry);
    bridge_free(bridge);
    ret = LAGOPUS_RESULT_OK;
  } else {
    ret = LAGOPUS_RESULT_NOT_FOUND;
  }
  flowdb_wrunlock(NULL);
  /* not implemented yet. */
  return ret;
}
Esempio n. 5
0
/* Add port to the bridge. */
lagopus_result_t
bridge_port_add(struct bridge_list *bridge_list, const char *name,
                struct port *port) {
  struct bridge *bridge;
  lagopus_result_t ret;

  flowdb_wrlock(NULL);
  /* Lookup bridge by name. */
  bridge = bridge_lookup(bridge_list, name);
  if (bridge != NULL) {
    /* Set port to the bridge's port vector. */
    printf("Assigning port id %u to bridge %s\n",
           port->ifindex, bridge->name);
    vector_set_index(bridge->ports, port->ofp_port.port_no, port);
    port->bridge = bridge;
    send_port_status(port, OFPPR_ADD);
    ret = LAGOPUS_RESULT_OK;
  } else {
    ret = LAGOPUS_RESULT_NOT_FOUND;
  }

  flowdb_wrunlock(NULL);
  return ret;
}
Esempio n. 6
0
/* Lookup bridge. */
struct bridge *
dpmgr_bridge_lookup(struct dpmgr *dpmgr, const char *bridge_name) {
  return bridge_lookup(&dpmgr->bridge_list, bridge_name);
}
Esempio n. 7
0
unsigned int
vr_bridge_input(struct vrouter *router, struct vr_packet *pkt,
                struct vr_forwarding_md *fmd)
{
    int reason, handled;
    l4_pkt_type_t l4_type = L4_TYPE_UNKNOWN;
    unsigned short pull_len, overlay_len = VROUTER_OVERLAY_LEN;

    int8_t *dmac;
    struct vr_bridge_entry *be;
    struct vr_nexthop *nh = NULL;
    struct vr_vrf_stats *stats;

    dmac = (int8_t *) pkt_data(pkt);

    if (pkt->vp_if->vif_flags & VIF_FLAG_MAC_LEARN) {
        if (vr_bridge_learn(router, pkt, fmd)) {
            return 0;
        }
    }

    pull_len = 0;
    if ((pkt->vp_type == VP_TYPE_IP) || (pkt->vp_type == VP_TYPE_IP6) ||
            (pkt->vp_type == VP_TYPE_ARP)) {
        pull_len = pkt_get_network_header_off(pkt) - pkt_head_space(pkt);
        if (pull_len && !pkt_pull(pkt, pull_len)) {
            vr_pfree(pkt, VP_DROP_PULL);
            return 0;
        }
    }

    if ((pkt->vp_type == VP_TYPE_IP) || (pkt->vp_type == VP_TYPE_IP6)) {
        if (fmd->fmd_dscp < 0) {
            if (pkt->vp_type == VP_TYPE_IP) {
                fmd->fmd_dscp =
                    vr_inet_get_tos((struct vr_ip *)pkt_network_header(pkt));
            } else if (pkt->vp_type == VP_TYPE_IP6) {
                fmd->fmd_dscp =
                    vr_inet6_get_tos((struct vr_ip6 *)pkt_network_header(pkt));
            }
        }
    } else {
        if (fmd->fmd_dotonep < 0) {
            fmd->fmd_dotonep = vr_vlan_get_tos(pkt_data(pkt));
        }
    }

    /* Do the bridge lookup for the packets not meant for "me" */
    if (!fmd->fmd_to_me) {
        /*
         * If DHCP packet coming from VM, Trap it to Agent before doing the bridge
         * lookup itself
         */
        if (vif_is_virtual(pkt->vp_if)) {
            if (pkt->vp_type == VP_TYPE_IP)
                l4_type = vr_ip_well_known_packet(pkt);
            else if (pkt->vp_type == VP_TYPE_IP6)
                l4_type = vr_ip6_well_known_packet(pkt);

            if (l4_type == L4_TYPE_DHCP_REQUEST) {
                if (pkt->vp_if->vif_flags & VIF_FLAG_DHCP_ENABLED) {
                    vr_trap(pkt, fmd->fmd_dvrf,  AGENT_TRAP_L3_PROTOCOLS, NULL);
                    return 0;
                }
            }

            /*
             * Handle the unicast ARP, coming from VM, not
             * destined to us. Broadcast ARP requests would be handled
             * in L2 multicast nexthop. Multicast ARP on fabric
             * interface also would be handled in L2 multicast nexthop.
             * Unicast ARP packets on fabric interface would be handled
             * in plug routines of interface.
             */
            if (!IS_MAC_BMCAST(dmac)) {
                handled = 0;
                if (pkt->vp_type == VP_TYPE_ARP) {
                    handled = vr_arp_input(pkt, fmd, dmac);
                } else if (l4_type == L4_TYPE_NEIGHBOUR_SOLICITATION) {
                    handled = vr_neighbor_input(pkt, fmd, dmac);
                }

                if (handled)
                    return 0;
            }
        }

        be = bridge_lookup(dmac, fmd);
        if (be)
            nh = be->be_nh;

        if (!nh || nh->nh_type == NH_DISCARD) {

            /* If Flooding of unknown unicast not allowed, drop the packet */
            if (!vr_unknown_uc_flood(pkt->vp_if, pkt->vp_nh) ||
                                 IS_MAC_BMCAST(dmac)) {
                vr_pfree(pkt, VP_DROP_L2_NO_ROUTE);
                return 0;
            }

            be = bridge_lookup(vr_bcast_mac, fmd);
            nh = be->be_nh;
            if (!nh) {
                vr_pfree(pkt, VP_DROP_L2_NO_ROUTE);
                return 0;
            }
            stats = vr_inet_vrf_stats(fmd->fmd_dvrf, pkt->vp_cpu);
            if (stats)
                stats->vrf_uuc_floods++;

            /* Treat this unknown unicast packet as multicast */
            pkt->vp_flags |= VP_FLAG_MULTICAST;
        }

        if (be)
            __sync_fetch_and_add(&be->be_packets, 1);

        if (nh->nh_type != NH_L2_RCV)
            overlay_len = VROUTER_L2_OVERLAY_LEN;
    }


    /* Adjust MSS for V4 and V6 packets */
    if ((pkt->vp_type == VP_TYPE_IP) || (pkt->vp_type == VP_TYPE_IP6)) {

        if (vif_is_virtual(pkt->vp_if) &&
                vr_from_vm_mss_adj && vr_pkt_from_vm_tcp_mss_adj) {

            if ((reason = vr_pkt_from_vm_tcp_mss_adj(pkt, overlay_len))) {
                vr_pfree(pkt, reason);
                return 0;
            }
        }

        if (fmd->fmd_to_me) {
            handled = vr_l3_input(pkt, fmd);
            if (!handled) {
                vr_pfree(pkt, VP_DROP_NOWHERE_TO_GO);
            }
            return 0;
        }
    }

    if (pull_len && !pkt_push(pkt, pull_len)) {
        vr_pfree(pkt, VP_DROP_PUSH);
        return 0;
    }

    nh_output(pkt, nh, fmd);
    return 0;
}
Esempio n. 8
0
unsigned int
vr_bridge_learn(struct vrouter *router, struct vr_packet *pkt,
        struct vr_forwarding_md *fmd)
{
    int ret = 0, lock, valid_src;
    unsigned int trap_reason;
    bool trap = false;

    struct vr_eth *eth;
    struct vr_packet *pkt_c;
    struct vr_nexthop *nh = NULL;
    struct vr_bridge_entry *be;

    eth = (struct vr_eth *)pkt_data(pkt);
    if (!eth)
        return 0;

    if (IS_MAC_BMCAST(eth->eth_smac))
        return 0;

    be = bridge_lookup(eth->eth_smac, fmd);
    if (be) {
        nh = be->be_nh;
    }

    if (!nh) {
        be = bridge_lookup((uint8_t *)vr_bcast_mac, fmd);
        if (be) {
            nh = be->be_nh;
        }

        if (!nh)
            return 0;

        lock = bridge_table_lock(pkt->vp_if, eth->eth_smac);
        if (lock < 0)
            return 0;

        be = bridge_add(0, fmd->fmd_dvrf, eth->eth_smac, nh->nh_id);
        bridge_table_unlock(pkt->vp_if, eth->eth_smac, lock);
        if (!be)
            return -ENOMEM;

        trap_reason = AGENT_TRAP_MAC_LEARN;
        trap = true;
    } else {
        if (!(be->be_flags & VR_BE_MAC_MOVED_FLAG) && (nh->nh_validate_src)) {
            valid_src = nh->nh_validate_src(pkt, nh, fmd, NULL);
            if (valid_src != NH_SOURCE_VALID) {
                ret = vr_bridge_set_route_flags(be, VR_BE_MAC_MOVED_FLAG);
                if (!ret) {
                    /* trap the packet for mac move */
                    trap_reason = AGENT_TRAP_MAC_MOVE;
                    trap = true;
                }
                ret = 0;
            }
        }
    }

    __sync_fetch_and_add(&be->be_packets, 1);

    if (trap) {
        pkt_c = pkt_cow(pkt, 0);
        if (!pkt_c) {
            pkt_c = pkt;
            ret = -ENOMEM;
        }

        vr_trap(pkt_c, fmd->fmd_dvrf,
                trap_reason, (void *)&be->be_hentry.hentry_index);
    }

    return ret;
}