/*****************************************************************//**
* \brief Include all ports to default vlan
*
* \param unit   [IN]    unit number
*
* \return OPENNSL_E_XXX     OpenNSL API return code
  ********************************************************************/
int switch_default_vlan_config(int unit)
{
  opennsl_port_config_t pcfg;
  opennsl_pbmp_t upbm;
  int rv;

  OPENNSL_PBMP_CLEAR(upbm);
  /*
   * Create VLAN with id DEFAULT_VLAN and
   * add ethernet ports to the VLAN
   */
  rv = opennsl_port_config_get(unit, &pcfg);
  if (rv != OPENNSL_E_NONE) {
    printf("Failed to get port configuration. Error %s\n", opennsl_errmsg(rv));
    return rv;
  }

  rv = opennsl_vlan_port_add(unit, DEFAULT_VLAN, pcfg.e, upbm);
  if (rv != OPENNSL_E_NONE) {
    printf("Failed to add ports to VLAN. Error %s\n", opennsl_errmsg(rv));
    return rv;
  }

  return 0;
}
示例#2
0
/*****************************************************************//**
 * \brief Form a packet and send multiple packets from the specified port
 *
 * \param unit	[IN]	Unit number.
 * \param port	[IN]	Port number.
 * \param count	[IN]	Number of packets to be transmitted.
 *
 * \return OPENNSL_E_XXX     OpenNSL API return code
 ********************************************************************/
void example_multi_pkt_send(int unit, int port, int count)
{
  int i;
  int rv;
  char data[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x82, 0x2f,
                 0x2e, 0x42, 0x46, 0x74, 0x08, 0x06, 0x00, 0x01,
                 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x82, 0x2f,
                 0x2e, 0x42, 0x46, 0x74, 0x0a, 0x00, 0x00, 0x01,
                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
                 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 };

  for (i = 0; i < count; i++)
  {
    rv = example_pkt_send(unit, port, data, (int) sizeof(data));

    if (!OPENNSL_SUCCESS(rv))
    {
      printf("Error Sending Packet: %d.  Error: %s\n", i + 1, opennsl_errmsg(rv));
    }
    else
    {
      printf("Transmitted Packet %d of size %zu\n", i + 1, sizeof(data));
    }
  }
}
示例#3
0
BcmUnit::~BcmUnit() {
  if (attached_.load(std::memory_order_acquire)) {
    auto rv = opennsl_detach(unit_);
    CHECK(OPENNSL_SUCCESS(rv)) <<
        "failed to detach BCM unit " << unit_ << ": " << opennsl_errmsg(rv);
  }
  // Unregister ourselves from BcmAPI.
  BcmAPI::unitDestroyed(this);
}
示例#4
0
文件: BcmPort.cpp 项目: XPliant/fboss
void BcmPort::updateStat(std::chrono::seconds now,
                         stats::MonotonicCounter* stat,
                         opennsl_stat_val_t type) {
  // Use the non-sync API to just get the values accumulated in software.
  // The Broadom SDK's counter thread syncs the HW counters to software every
  // 500000us (defined in config.bcm).
  uint64_t value;
  auto ret = opennsl_stat_get(unit_, port_, type, &value);
  if (OPENNSL_FAILURE(ret)) {
    LOG(ERROR) << "Failed to get stat " << type << " for port " << port_
               << " :" << opennsl_errmsg(ret);
    return;
  }
  stat->updateValue(now, value);
}
示例#5
0
bool BcmRoute::deleteLpmRoute(int unitNumber,
                              opennsl_vrf_t vrf,
                              const folly::IPAddress& prefix,
                              uint8_t prefixLength) {
  opennsl_l3_route_t rt;
  initL3RouteFromArgs(&rt, vrf, prefix, prefixLength);
  auto rc = opennsl_l3_route_delete(unitNumber, &rt);
  if (OPENNSL_FAILURE(rc)) {
    LOG(ERROR) << "Failed to delete a route entry for " << prefix << "/"
               << static_cast<int>(prefixLength)
               << " Error: " << opennsl_errmsg(rc);
    return false;
  } else {
    VLOG(3) << "deleted a route entry for " << prefix.str() << "/"
            << static_cast<int>(prefixLength);
  }
  return true;
}
示例#6
0
文件: BcmPort.cpp 项目: XPliant/fboss
void BcmPort::updateStats() {
  // TODO: It would be nicer to use a monotonic clock, but unfortunately
  // the ServiceData code currently expects everyone to use system time.
  auto now = duration_cast<seconds>(system_clock::now().time_since_epoch());

  updateStat(now, &inBytes_, opennsl_spl_snmpIfHCInOctets);
  updateStat(now, &inUnicastPkts_, opennsl_spl_snmpIfHCInUcastPkts);
  updateStat(now, &inMulticastPkts_, opennsl_spl_snmpIfHCInMulticastPkts);
  updateStat(now, &inBroadcastPkts_, opennsl_spl_snmpIfHCInBroadcastPkts);
  updateStat(now, &inDiscards_, opennsl_spl_snmpIfInDiscards);
  updateStat(now, &inErrors_, opennsl_spl_snmpIfInErrors);

  updateStat(now, &outBytes_, opennsl_spl_snmpIfHCOutOctets);
  updateStat(now, &outUnicastPkts_, opennsl_spl_snmpIfHCOutUcastPkts);
  updateStat(now, &outMulticastPkts_, opennsl_spl_snmpIfHCOutMulticastPkts);
  updateStat(now, &outBroadcastPkts_, opennsl_spl_snmpIfHCOutBroadcastPckts);
  updateStat(now, &outDiscards_, opennsl_spl_snmpIfOutDiscards);
  updateStat(now, &outErrors_, opennsl_spl_snmpIfOutErrors);

  setAdditionalStats(now);

  // Update the queue length stat
  uint32_t qlength;
  auto ret = opennsl_port_queued_count_get(unit_, port_, &qlength);
  if (OPENNSL_FAILURE(ret)) {
    LOG(ERROR) << "Failed to get queue length for port " << port_
               << " :" << opennsl_errmsg(ret);
  } else {
    SpinLockHolder guard(outQueueLen_.first.get());
    outQueueLen_.second->addValue(now, qlength);
    // TODO: outQueueLen_ only exports the average queue length over the last
    // 60 seconds, 10 minutes, etc.
    // We should also export the current value.  We could use a simple counter
    // or a dynamic counter for this.
  }

  // Update the packet length histograms
  updatePktLenHist(now, &inPktLengths_, kInPktLengthStats);
  updatePktLenHist(now, &outPktLengths_, kOutPktLengthStats);
};
示例#7
0
void BcmPort::updatePktLenHist(
    std::chrono::seconds now,
    stats::ExportedHistogramMapImpl::LockableHistogram* hist,
    const std::vector<opennsl_stat_val_t>& stats) {
  // Get the counter values
  uint64_t counters[10];
  // opennsl_stat_multi_get() unfortunately doesn't correctly const qualify
  // it's stats arguments right now.
  opennsl_stat_val_t* statsArg =
      const_cast<opennsl_stat_val_t*>(&stats.front());
  auto ret = opennsl_stat_multi_get(unit_, port_,
                                stats.size(), statsArg, counters);
  if (OPENNSL_FAILURE(ret)) {
    LOG(ERROR) << "Failed to get packet length stats for port " << port_
               << " :" << opennsl_errmsg(ret);
    return;
  }

  // Update the histogram
  auto guard = hist->makeLockGuard();
  for (int idx = 0; idx < stats.size(); ++idx) {
    hist->addValueLocked(guard, now.count(), idx, counters[idx]);
  }
}
示例#8
0
void BcmPort::updateStats() {
  // TODO: It would be nicer to use a monotonic clock, but unfortunately
  // the ServiceData code currently expects everyone to use system time.
  if (!shouldReportStats()) {
    return;
  }
  auto now = duration_cast<seconds>(system_clock::now().time_since_epoch());
  HwPortStats curPortStats;
  updateStat(
      now, kInBytes, opennsl_spl_snmpIfHCInOctets, &curPortStats.inBytes_);
  updateStat(
      now,
      kInUnicastPkts,
      opennsl_spl_snmpIfHCInUcastPkts,
      &curPortStats.inUnicastPkts_);
  updateStat(
      now,
      kInMulticastPkts,
      opennsl_spl_snmpIfHCInMulticastPkts,
      &curPortStats.inMulticastPkts_);
  updateStat(
      now,
      kInBroadcastPkts,
      opennsl_spl_snmpIfHCInBroadcastPkts,
      &curPortStats.inBroadcastPkts_);
  updateStat(
      now,
      kInDiscards,
      opennsl_spl_snmpIfInDiscards,
      &curPortStats.inDiscards_);
  updateStat(
      now, kInErrors, opennsl_spl_snmpIfInErrors, &curPortStats.inErrors_);
  updateStat(
      now,
      kInIpv4HdrErrors,
      opennsl_spl_snmpIpInHdrErrors,
      &curPortStats.inIpv4HdrErrors_);
  updateStat(
      now,
      kInIpv6HdrErrors,
      opennsl_spl_snmpIpv6IfStatsInHdrErrors,
      &curPortStats.inIpv6HdrErrors_);
  updateStat(
      now,
      kInPause,
      opennsl_spl_snmpDot3InPauseFrames,
      &curPortStats.inPause_);
  // Egress Stats
  updateStat(
      now, kOutBytes, opennsl_spl_snmpIfHCOutOctets, &curPortStats.outBytes_);
  updateStat(
      now,
      kOutUnicastPkts,
      opennsl_spl_snmpIfHCOutUcastPkts,
      &curPortStats.outUnicastPkts_);
  updateStat(
      now,
      kOutMulticastPkts,
      opennsl_spl_snmpIfHCOutMulticastPkts,
      &curPortStats.outMulticastPkts_);
  updateStat(
      now,
      kOutBroadcastPkts,
      opennsl_spl_snmpIfHCOutBroadcastPckts,
      &curPortStats.outBroadcastPkts_);
  updateStat(
      now,
      kOutDiscards,
      opennsl_spl_snmpIfOutDiscards,
      &curPortStats.outDiscards_);
  updateStat(
      now, kOutErrors, opennsl_spl_snmpIfOutErrors, &curPortStats.outErrors_);
  updateStat(
      now,
      kOutPause,
      opennsl_spl_snmpDot3OutPauseFrames,
      &curPortStats.outPause_);

  setAdditionalStats(now, &curPortStats);
  // Compute non pause discards
  const auto kUninit = hardware_stats_constants::STAT_UNINITIALIZED();
  if (isMmuLossy() && portStats_.inDiscards_ != kUninit &&
      portStats_.inPause_ != kUninit) {
    // If MMU setup as lossy, all incoming pause frames will be
    // discarded and will count towards in discards. This makes in discards
    // counter somewhat useless. So instead calculate "in_non_pause_discards",
    // as std::max(0, (inDiscardsSincePrev - inPauseSincePrev)).
    // std::max(..) is used, since stats from  h/w are synced non atomically,
    // So depending on what get synced later # of pause maybe be slightly
    // higher than # of discards.
    auto inPauseSincePrev = curPortStats.inPause_ - portStats_.inPause_;
    auto inDiscardsSincePrev =
        curPortStats.inDiscards_ - portStats_.inDiscards_;
    if (inPauseSincePrev >= 0 && inDiscardsSincePrev >=0) {
      // Account for counter rollover.
      auto inNonPauseDiscardsSincePrev =
          std::max(0L, (inDiscardsSincePrev - inPauseSincePrev));
      // Init current port stats from prev value or 0
      curPortStats.inNonPauseDiscards_ =
          (portStats_.inNonPauseDiscards_ == kUninit
               ? 0
               : portStats_.inNonPauseDiscards_);
      // Counters are cumalative
      curPortStats.inNonPauseDiscards_ += inNonPauseDiscardsSincePrev;
      auto inNonPauseDiscards = getPortCounterIf(kInNonPauseDiscards);
      inNonPauseDiscards->updateValue(now, curPortStats.inNonPauseDiscards_);
    }
  }
  portStats_ = curPortStats;

  // Update the queue length stat
  uint32_t qlength;
  auto ret = opennsl_port_queued_count_get(unit_, port_, &qlength);
  if (OPENNSL_FAILURE(ret)) {
    LOG(ERROR) << "Failed to get queue length for port " << port_
               << " :" << opennsl_errmsg(ret);
  } else {
    outQueueLen_.addValue(now.count(), qlength);
    // TODO: outQueueLen_ only exports the average queue length over the last
    // 60 seconds, 10 minutes, etc.
    // We should also export the current value.  We could use a simple counter
    // or a dynamic counter for this.
  }

  // Update the packet length histograms
  updatePktLenHist(now, &inPktLengths_, kInPktLengthStats);
  updatePktLenHist(now, &outPktLengths_, kOutPktLengthStats);
};
示例#9
0
/*****************************************************************//**
 * \brief Main function for packet transmission
 *
 * \param argc, argv         commands line arguments
 *
 * \return OPENNSL_E_XXX     OpenNSL API return code
 ********************************************************************/
int main(int argc, char *argv[])
{
  opennsl_error_t   rv;
  int count;
  opennsl_port_t port;
  int unit = DEFAULT_UNIT;
  int choice;
  int index = 0;

  if(strcmp(argv[0], "gdb") == 0)
  {
    index = 1;
  }

  if((argc != (index + 1)) || ((argc > (index + 1)) && (strcmp(argv[index + 1], "--help") == 0))) {
    printf("%s\n\r", example_usage);
    return OPENNSL_E_PARAM;
  }

  /* Initialize the system. */
  printf("Initializing the system.\r\n");
  rv = opennsl_driver_init((opennsl_init_t *) NULL);

  if(rv != OPENNSL_E_NONE) {
    printf("\r\nFailed to initialize the system. Error %s\r\n",
        opennsl_errmsg(rv));
    return rv;
  }

  /* Add ports to default vlan. */
  printf("Adding ports to default vlan.\r\n");
  rv = example_switch_default_vlan_config(unit);
  if(rv != OPENNSL_E_NONE) {
    printf("\r\nFailed to add default ports. rv: %s\r\n", opennsl_errmsg(rv));
    return rv;
  }

  while (1) {
    printf("\r\nUser menu: Select one of the following options\r\n");
    printf("1. Transmit a packet\n");
    printf("2. Display OpenNSL version\n");
    printf("9. Launch diagnostic shell\n");
    printf("0. Quit the application\n");

    if(example_read_user_choice(&choice) != OPENNSL_E_NONE)
    {
        printf("Invalid option entered. Please re-enter.\n");
        continue;
    }
    switch(choice){

      case 1:
      {
        printf("\r\nEnter the port on which packet needs to be transmitted.\r\n");
        if(example_read_user_choice(&port) != OPENNSL_E_NONE)
        {
            printf("Invalid option entered. Please re-enter.\n");
            continue;
        }

        printf("\r\nEnter number of packets to be sent.\r\n");
        if(example_read_user_choice(&count) != OPENNSL_E_NONE)
        {
            printf("Invalid option entered. Please re-enter.\n");
            continue;
        }

        /* Transmit packet(s) on the specified port */
        example_multi_pkt_send(unit, port, count);

        break;
      } /* End of case 1 */

      case 2:
      {
        printf("OpenNSL version: %s\n", opennsl_version_get());
        break;
      }

      case 9:
      {
        opennsl_driver_shell();
        break;
      }

      case 0:
      {
        printf("Exiting the application.\n");
        return OPENNSL_E_NONE;
      }

      default:
        break;
    } /* End of switch */
  } /* End of while */

  return OPENNSL_E_NONE;
}
示例#10
0
/**************************************************************************//**
 * \brief To add a given set of ports and VLAN to spanning tree instance.
 *
 * \param    unit      [IN] Unit number.
 * \param    *info     [IN] Pointer to a location where STG information
 *                          is stored
 *
 * \return      OPENNSL_E_xxx  OpenNSL API return code
 *****************************************************************************/
int example_stg_create(int unit, stg_info_s *info) {
  int rv;
  opennsl_pbmp_t pbmp;

  /* create VLAN */
  rv = opennsl_vlan_create(DEFAULT_UNIT, info->vlan_1);
  if (rv != OPENNSL_E_NONE) {
    printf("Error, in opennsl_vlan_create, vid=%d, \n", info->vlan_1);
    return rv;
  }

  if(verbose >= 2) {
    printf("VLAN %d is created.\n", info->vlan_1);
  }

  OPENNSL_PBMP_CLEAR(pbmp);
  OPENNSL_PBMP_PORT_ADD(pbmp, info->port_1);
  OPENNSL_PBMP_PORT_ADD(pbmp, info->port_2);

  rv = opennsl_vlan_port_add(unit, info->vlan_1, pbmp, pbmp);
  if (rv != OPENNSL_E_NONE) {
    printf("OPENNSL FAIL %d: %s\n", rv, opennsl_errmsg(rv));
    return rv;
  }

  if(verbose >= 2) {
    printf("Added ports %d, %d to VLAN %d.\n",
           info->port_1, info->port_2, info->vlan_1);
  }

  /* add the vlans to the stg */
  rv = opennsl_stg_vlan_add(unit, info->stg, info->vlan_1);
  if (rv != OPENNSL_E_NONE) {
    printf("Error, in opennsl_stg_vlan_add, vid=%d, \n", info->vlan_1);
    return rv;
  }

  if(verbose >= 2) {
    printf("Attached VLAN %d to Spanning Tree Group %d.\n",
           info->vlan_1, info->stg);
  }

  /* add two ports to the stg and attach stp state for each of them */
  rv = opennsl_stg_stp_set(unit, info->stg, info->port_1, info->stp_state_1);
  if (rv != OPENNSL_E_NONE) {
    printf("Error, in opennsl_stg_stp_set, stg=%d, \n", info->stg);
    return rv;
  }

  if(verbose >= 2) {
    printf("STP state of port %d is set to \"%s\".\n", 
           info->port_1, stp_state_str[info->stp_state_1]);
  }

  rv = opennsl_stg_stp_set(unit, info->stg, info->port_2, info->stp_state_2);
  if (rv != OPENNSL_E_NONE) {
    printf("Error, in opennsl_stg_stp_set, stg=%d, \n", info->stg);
    return rv;
  }
  if(verbose >= 2) {
    printf("STP state of port %d is set to \"%s\".\n",
           info->port_2, stp_state_str[info->stp_state_2]);
  }

  return OPENNSL_E_NONE;
}