00001 
00002 
00003 #include "ace/ATM_QoS.h"
00004 
00005 ACE_RCSID(ace, ATM_QoS, "$Id: ATM_QoS.cpp 79134 2007-07-31 18:23:50Z johnnyw $")
00006 
00007 #if defined (ACE_HAS_ATM)
00008 
00009 #if !defined (__ACE_INLINE__)
00010 #include "ace/ATM_QoS.inl"
00011 #endif 
00012 
00013 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00014 
00015 #if defined (ACE_HAS_FORE_ATM_XTI) || defined (ACE_HAS_FORE_ATM_WS2)
00016 #define BHLI_MAGIC "FORE_ATM"
00017 
00018 const long ACE_ATM_QoS::LINE_RATE = 353207;
00019 const int ACE_ATM_QoS::OPT_FLAGS_CPID = 0x1;
00020 const int ACE_ATM_QoS::OPT_FLAGS_PMP = 0x2;
00021 const int ACE_ATM_QoS::DEFAULT_SELECTOR = 0x99;
00022 const int ACE_ATM_QoS::DEFAULT_PKT_SIZE = 8192;
00023 #elif defined (ACE_HAS_LINUX_ATM)
00024 
00025 
00026 
00027 const long ACE_ATM_QoS::LINE_RATE = 353207;
00028 const int ACE_ATM_QoS::OPT_FLAGS_CPID = 0x1;
00029 const int ACE_ATM_QoS::OPT_FLAGS_PMP = 0x2;
00030 const int ACE_ATM_QoS::DEFAULT_SELECTOR = 0x99;
00031 const int ACE_ATM_QoS::DEFAULT_PKT_SIZE = 8192;
00032 #else
00033 const long ACE_ATM_QoS::LINE_RATE = 0L;
00034 const int ACE_ATM_QoS::OPT_FLAGS_CPID = 0;
00035 const int ACE_ATM_QoS::OPT_FLAGS_PMP = 0;
00036 const int ACE_ATM_QoS::DEFAULT_SELECTOR = 0x0;
00037 const int ACE_ATM_QoS::DEFAULT_PKT_SIZE = 0;
00038 #endif 
00039 
00040 ACE_ALLOC_HOOK_DEFINE(ACE_ATM_QoS)
00041 
00042 ACE_ATM_QoS::ACE_ATM_QoS (int pktSize)
00043 {
00044   ACE_TRACE ("ACE_ATM_QoS::ACE_ATM_QoS");
00045 #if defined (ACE_HAS_LINUX_ATM)
00046     ACE_OS::memset(&qos_, 0, sizeof(qos_));
00047     qos_.aal = ATM_PROTOCOL_DEFAULT;
00048     qos_.rxtp.traffic_class = ATM_ANYCLASS;
00049     qos_.rxtp.max_sdu = pktSize;
00050     qos_.txtp.traffic_class = ATM_ANYCLASS;
00051     qos_.txtp.max_sdu = pktSize;
00052 #else
00053     ACE_UNUSED_ARG (pktSize);
00054 #endif 
00055 }
00056 
00057 ACE_ATM_QoS::ACE_ATM_QoS(int rate,
00058                          int pktSize)
00059 {
00060   ACE_TRACE( "ACE_ATM_QoS::ACE_ATM_QoS" );
00061 #if defined (ACE_HAS_FORE_ATM_WS2)
00062   AAL_PARAMETERS_IE ie_aalparams;
00063   ATM_TRAFFIC_DESCRIPTOR_IE ie_td;
00064   ATM_BROADBAND_BEARER_CAPABILITY_IE ie_bbc;
00065   ATM_QOS_CLASS_IE ie_qos;
00066   Q2931_IE *ie_ptr;
00067   int size;
00068 
00069   
00070   ie_aalparams.AALType = AALTYPE_5;
00071   ie_aalparams.AALSpecificParameters.AAL5Parameters.ForwardMaxCPCSSDUSize
00072     = pktSize; 
00073   ie_aalparams.AALSpecificParameters.AAL5Parameters.BackwardMaxCPCSSDUSize
00074     = pktSize; 
00075   ie_aalparams.AALSpecificParameters.AAL5Parameters.Mode = AAL5_MODE_MESSAGE;
00076   ie_aalparams.AALSpecificParameters.AAL5Parameters.SSCSType = AAL5_SSCS_NULL;
00077 
00078   size = sizeof(Q2931_IE_TYPE) + sizeof(ULONG) + sizeof(AAL_PARAMETERS_IE);
00079 
00080   ie_td.Forward.PeakCellRate_CLP0 = SAP_FIELD_ABSENT;
00081   ie_td.Forward.PeakCellRate_CLP01 = rate;
00082   ie_td.Forward.SustainableCellRate_CLP0 = SAP_FIELD_ABSENT;
00083   ie_td.Forward.SustainableCellRate_CLP01 = SAP_FIELD_ABSENT;
00084   ie_td.Forward.MaxBurstSize_CLP0 = SAP_FIELD_ABSENT;
00085   ie_td.Forward.MaxBurstSize_CLP01 = SAP_FIELD_ABSENT;
00086   ie_td.Forward.Tagging = SAP_FIELD_ABSENT;
00087 
00088   ie_td.Backward.PeakCellRate_CLP0 = SAP_FIELD_ABSENT;
00089   ie_td.Backward.PeakCellRate_CLP01 = rate;
00090   ie_td.Backward.SustainableCellRate_CLP0 = SAP_FIELD_ABSENT;
00091   ie_td.Backward.SustainableCellRate_CLP01 = SAP_FIELD_ABSENT;
00092   ie_td.Backward.MaxBurstSize_CLP0 = SAP_FIELD_ABSENT;
00093   ie_td.Backward.MaxBurstSize_CLP01 = SAP_FIELD_ABSENT;
00094   ie_td.Backward.Tagging = SAP_FIELD_ABSENT;
00095 
00096   ie_td.BestEffort = 0; 
00097 
00098   size += sizeof( Q2931_IE_TYPE )
00099     + sizeof( ULONG )
00100     + sizeof( ATM_TRAFFIC_DESCRIPTOR_IE );
00101 
00102   ie_bbc.BearerClass = BCOB_X;
00103   ie_bbc.TrafficType = TT_CBR;
00104   ie_bbc.TimingRequirements = TR_END_TO_END;
00105   ie_bbc.ClippingSusceptability = CLIP_NOT;
00106   ie_bbc.UserPlaneConnectionConfig = UP_P2P;
00107 
00108   size += sizeof( Q2931_IE_TYPE )
00109     + sizeof( ULONG )
00110     + sizeof( ATM_BROADBAND_BEARER_CAPABILITY_IE );
00111 
00112   ie_qos.QOSClassForward = QOS_CLASS1;
00113   ie_qos.QOSClassBackward = QOS_CLASS1; 
00114   
00115 
00116   size += sizeof(Q2931_IE_TYPE) + sizeof(ULONG) + sizeof(ATM_QOS_CLASS_IE);
00117 
00118   qos_.ProviderSpecific.buf = (char *) ACE_OS::malloc(size);
00119   if (qos_.ProviderSpecific.buf == 0) {
00120     ACE_ERROR((LM_ERROR,
00121                ACE_TEXT ("ACE_ATM_QoS::ACE_ATM_QoS: Unable to allocate %d bytes for qos_.ProviderSpecific.buf\n"),
00122                size));
00123     return;
00124   }
00125   qos_.ProviderSpecific.len = size;
00126   ACE_OS::memset(qos_.ProviderSpecific.buf, 0, size);
00127 
00128   ie_ptr = (Q2931_IE *) qos_.ProviderSpecific.buf;
00129   ie_ptr->IEType = IE_AALParameters;
00130   ie_ptr->IELength = sizeof( Q2931_IE_TYPE )
00131     + sizeof( ULONG )
00132     + sizeof( AAL_PARAMETERS_IE );
00133   ACE_OS::memcpy(ie_ptr->IE, &ie_aalparams, sizeof(AAL_PARAMETERS_IE));
00134 
00135   ie_ptr = (Q2931_IE *) ((char *)ie_ptr + ie_ptr->IELength);
00136   ie_ptr->IEType = IE_TrafficDescriptor;
00137   ie_ptr->IELength = sizeof( Q2931_IE_TYPE )
00138     + sizeof( ULONG )
00139     + sizeof( ATM_TRAFFIC_DESCRIPTOR_IE );
00140   ACE_OS::memcpy(ie_ptr->IE, &ie_td, sizeof(ATM_TRAFFIC_DESCRIPTOR_IE));
00141 
00142   ie_ptr = (Q2931_IE *) ((char *)ie_ptr + ie_ptr->IELength);
00143   ie_ptr->IEType = IE_BroadbandBearerCapability;
00144   ie_ptr->IELength = sizeof( Q2931_IE_TYPE )
00145     + sizeof( ULONG )
00146     + sizeof( ATM_BROADBAND_BEARER_CAPABILITY_IE );
00147   ACE_OS::memcpy(ie_ptr->IE,
00148                  &ie_bbc,
00149                  sizeof(ATM_BROADBAND_BEARER_CAPABILITY_IE));
00150 
00151   ie_ptr = (Q2931_IE *) ((char *)ie_ptr + ie_ptr->IELength);
00152   ie_ptr->IEType = IE_QOSClass;
00153   ie_ptr->IELength = sizeof( Q2931_IE_TYPE )
00154     + sizeof( ULONG )
00155     + sizeof( ATM_QOS_CLASS_IE );
00156   ACE_OS::memcpy(ie_ptr->IE, &ie_qos, sizeof(ATM_QOS_CLASS_IE));
00157 
00158   
00159   
00160   
00161   
00162   
00163   
00164   
00165   
00166   
00167 
00168   
00169   
00170   
00171   
00172   
00173   
00174   
00175   
00176   
00177 
00178   ACE_Flow_Spec send_fspec( 0xffffffff,
00179                             0xffffffff,
00180                             0xffffffff,
00181                             0xffffffff,
00182                             0xffffffff,
00183                             SERVICETYPE_BESTEFFORT,
00184                             
00185                             0xffffffff,
00186                             0xffffffff,
00187                             15,
00188                             ACE_DEFAULT_THREAD_PRIORITY ),
00189     recv_fspec( 0xffffffff,
00190                 0xffffffff,
00191                 0xffffffff,
00192                 0xffffffff,
00193                 0xffffffff,
00194                 SERVICETYPE_BESTEFFORT,
00195                 
00196                 0xffffffff,
00197                 0,
00198                 15,
00199                 ACE_DEFAULT_THREAD_PRIORITY );
00200 
00201   qos_.sending_flowspec (send_fspec);
00202   qos_.receiving_flowspec (recv_fspec);
00203 #elif defined (ACE_HAS_FORE_ATM_XTI)
00204   ACE_UNUSED_ARG (rate);
00205   ACE_UNUSED_ARG (pktSize);
00206 #elif defined (ACE_HAS_LINUX_ATM)
00207   ACE_OS::memset(&qos_,
00208                  0,
00209                  sizeof(qos_));
00210   qos_.aal = ATM_PROTOCOL_DEFAULT;
00211   qos_.rxtp.max_sdu = pktSize;
00212 
00213   if (rate > 0) {
00214     qos_.rxtp.pcr = rate;
00215     qos_.rxtp.traffic_class = ATM_CBR;
00216     qos_.txtp.traffic_class = ATM_CBR;
00217     qos_.txtp.pcr = rate;
00218   }
00219   else {
00220     qos_.rxtp.traffic_class = ATM_UBR;
00221     qos_.txtp.traffic_class = ATM_UBR;
00222   }
00223 
00224   qos_.txtp.max_sdu = pktSize;
00225 #else
00226   ACE_UNUSED_ARG (rate);
00227 #endif 
00228 }
00229 
00230 void
00231 ACE_ATM_QoS::set_cbr_rate (int rate,
00232                            int pktSize)
00233 {
00234   ACE_TRACE ("ACE_ATM_QoS::set_cbr_rate");
00235 #if defined (ACE_HAS_FORE_ATM_WS2)
00236   
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245   ACE_OS::printf( "ATM_QoS(set_cbr_rate): set rate to %d c/s\n", rate );
00246 
00247   
00248   
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 
00271 
00272 
00273 
00274 
00275 
00276 
00277 
00278 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338   const int BYTES_PER_ATM_CELL = 53;
00339   ACE_OS::memset(&qos_, 0, sizeof(ATM_QoS));
00340   
00341   
00342   
00343   
00344   qos_.SendingFlowspec.TokenRate = 53000;               
00345   qos_.SendingFlowspec.TokenBucketSize = 32*1024;       
00346   
00347   qos_.SendingFlowspec.ServiceType = SERVICETYPE_GUARANTEED;
00348   
00349   
00350   qos_.SendingFlowspec.PeakBandwidth = rate * BYTES_PER_ATM_CELL;
00351   qos_.SendingFlowspec.Latency = -1;    
00352   qos_.SendingFlowspec.DelayVariation = -1; 
00353   
00354   qos_.ProviderSpecific.buf=0;
00355   qos_.ProviderSpecific.len=0;
00356   
00357 
00358   
00359   
00360   
00361   
00362   
00363   
00364   
00365   
00366   
00367 
00368   
00369   
00370   
00371   
00372   
00373   
00374   
00375   
00376   
00377 
00378   
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 #elif defined (ACE_HAS_FORE_ATM_XTI)
00406   ACE_UNUSED_ARG (rate);
00407   ACE_UNUSED_ARG (pktSize);
00408 #elif defined (ACE_HAS_LINUX_ATM)
00409   ACE_UNUSED_ARG (pktSize);
00410 
00411   qos_.rxtp.traffic_class = ATM_CBR;
00412   qos_.rxtp.pcr = rate;
00413   qos_.txtp.traffic_class = ATM_CBR;
00414   qos_.txtp.pcr = rate;
00415 #else
00416   ACE_UNUSED_ARG (rate);
00417 #endif 
00418 }
00419 
00420 void
00421 ACE_ATM_QoS::set_rate (ACE_HANDLE fd,
00422                        int rate,
00423                        int flags)
00424 {
00425   ACE_TRACE ("ACE_ATM_QoS::set_rate");
00426 #if defined (ACE_HAS_FORE_ATM_WS2) || defined (ACE_HAS_LINUX_ATM)
00427   set_cbr_rate( rate );
00428 
00429   ACE_UNUSED_ARG( fd );
00430   ACE_UNUSED_ARG( flags );
00431 #elif defined (ACE_HAS_FORE_ATM_XTI)
00432   long optlen = 0;
00433   qos_.buf = construct_options(fd,
00434                                rate,
00435                                flags,
00436                                &optlen);
00437   qos_.len = optlen;
00438 #else
00439   ACE_UNUSED_ARG (rate);
00440 #endif 
00441 }
00442 
00443 char*
00444 ACE_ATM_QoS::construct_options (ACE_HANDLE fd,
00445                                 int rate,
00446                                 int flags,
00447                                 long *len)
00448 {
00449 #if defined (ACE_HAS_FORE_ATM_WS2) || defined (ACE_HAS_LINUX_ATM)
00450   ACE_UNUSED_ARG (fd);
00451   ACE_UNUSED_ARG (rate);
00452   ACE_UNUSED_ARG (flags);
00453   ACE_UNUSED_ARG (len);
00454   return (0);
00455 #elif defined (ACE_HAS_FORE_ATM_XTI)
00456   struct t_opthdr *popt;
00457   char *buf;
00458   int qos_cells;
00459   struct t_info info;
00460 
00461   if (ACE_OS::t_getinfo (fd, &info) == -1)
00462     {
00463       ACE_OS::t_error ("t_getinfo");
00464       return 0;
00465     }
00466 
00467   buf = (char *) ACE_OS::malloc (info.options);
00468 
00469   if (buf == 0)
00470     ACE_ERROR_RETURN ((LM_ERROR,
00471                        ACE_TEXT ("Unable to allocate %d bytes for options\n"),
00472                        info.options),
00473                       0);
00474 
00475   popt = (struct t_opthdr *) buf;
00476 
00477   if (flags & OPT_FLAGS_CPID)
00478     {
00479       
00480       
00481       t_atm_addr *source_addr;
00482 
00483       popt->len = sizeof (struct t_opthdr) + sizeof (t_atm_addr);
00484       popt->level = T_ATM_SIGNALING;
00485       popt->name = T_ATM_ORIG_ADDR;
00486       popt->status = 0;
00487 
00488       source_addr =
00489         (t_atm_addr *)((char *) popt + sizeof (struct t_opthdr));
00490 
00491       source_addr->address_format = T_ATM_ENDSYS_ADDR;
00492       source_addr->address_length = ATMNSAP_ADDR_LEN;
00493 
00494       ATMSAPAddress local_addr;
00495       struct t_bind boundaddr;
00496 
00497       boundaddr.addr.maxlen = sizeof(local_addr);
00498       boundaddr.addr.buf = (char *) &local_addr;
00499 
00500       
00501       if (ACE_OS::t_getname(fd,
00502                             &boundaddr.addr,
00503                             LOCALNAME) < 0)
00504         {
00505           ACE_OS::t_error("t_getname (local_address)");
00506           ACE_ERROR ((LM_ERROR,
00507                       ACE_TEXT ("Can't get local address!\n")));
00508           ACE_OS::free (buf);
00509           return 0;
00510         }
00511 
00512       ACE_OS::memcpy(source_addr->address,
00513                      local_addr.sap.t_atm_sap_addr.address,
00514                      ATMNSAP_ADDR_LEN);
00515 
00516       popt = T_OPT_NEXTHDR (buf, info.options , popt);
00517     }
00518 
00519   
00520   
00521   
00522 
00523   
00524   
00525 
00526   qos_cells = (rate * 1000) / (48*8);
00527 
00528   if ((qos_cells > 0 && qos_cells < LINE_RATE)
00529       || (ACE_BIT_ENABLED (flags, OPT_FLAGS_PMP)))
00530     {
00531       struct t_atm_bearer *bearer;
00532       struct t_atm_traffic *traffic;
00533 
00534       
00535       popt->len = sizeof (struct t_opthdr) + sizeof (struct t_atm_bearer);
00536       popt->level = T_ATM_SIGNALING;
00537       popt->name = T_ATM_BEARER_CAP;
00538       popt->status = 0;
00539 
00540       bearer = (struct t_atm_bearer *)((char *) popt +
00541                                        sizeof (struct t_opthdr));
00542       bearer->bearer_class = T_ATM_CLASS_X;
00543 
00544       if (qos_cells)
00545         {
00546           bearer->traffic_type = T_ATM_CBR;
00547           bearer->timing_requirements = T_ATM_END_TO_END;
00548         }
00549       else
00550         {
00551           bearer->traffic_type   = 0; 
00552           bearer->timing_requirements = 0;
00553         }
00554       bearer->clipping_susceptibility = T_ATM_NULL;
00555 
00556       if (ACE_BIT_ENABLED (flags, OPT_FLAGS_PMP))
00557         bearer->connection_configuration = T_ATM_1_TO_MANY;
00558       else
00559         bearer->connection_configuration = T_ATM_1_TO_1;
00560 
00561       popt = T_OPT_NEXTHDR (buf, info.options, popt);
00562 
00563       
00564       popt->len = sizeof (struct t_opthdr) + sizeof (struct t_atm_traffic);
00565       popt->level = T_ATM_SIGNALING;
00566       popt->name = T_ATM_TRAFFIC;
00567       popt->status = 0;
00568 
00569       traffic = (struct t_atm_traffic *)((char *) popt +
00570                                          sizeof (struct t_opthdr));
00571 
00572       traffic->forward.PCR_high_priority = T_ATM_ABSENT;
00573       traffic->forward.PCR_all_traffic = qos_cells ? qos_cells : LINE_RATE;
00574       traffic->forward.SCR_high_priority = T_ATM_ABSENT;
00575       traffic->forward.SCR_all_traffic = T_ATM_ABSENT;
00576       traffic->forward.MBS_high_priority = T_ATM_ABSENT;
00577       traffic->forward.MBS_all_traffic = T_ATM_ABSENT;
00578       traffic->forward.tagging = T_NO;
00579 
00580       traffic->backward.PCR_high_priority = T_ATM_ABSENT;
00581       traffic->backward.PCR_all_traffic =
00582         (ACE_BIT_ENABLED (flags, OPT_FLAGS_PMP))
00583         ? 0 : qos_cells ? qos_cells : LINE_RATE;
00584       traffic->backward.SCR_high_priority = T_ATM_ABSENT;
00585       traffic->backward.SCR_all_traffic = T_ATM_ABSENT;
00586       traffic->backward.MBS_high_priority = T_ATM_ABSENT;
00587       traffic->backward.MBS_all_traffic = T_ATM_ABSENT;
00588       traffic->backward.tagging = T_NO;
00589 
00590       traffic->best_effort = qos_cells ? T_NO : T_YES;
00591 
00592       popt = T_OPT_NEXTHDR (buf,
00593                             info.options,
00594                             popt);
00595     }
00596 
00597   if (qos_cells > 0 && qos_cells < LINE_RATE)
00598     {
00599       struct t_atm_qos *qos;
00600 
00601       
00602       popt->len = sizeof (struct t_opthdr) + sizeof (struct t_atm_qos);
00603       popt->level = T_ATM_SIGNALING;
00604       popt->name = T_ATM_QOS;
00605       popt->status = 0;
00606 
00607       qos = (struct t_atm_qos *)((char *) popt + sizeof (struct t_opthdr));
00608       qos->coding_standard = T_ATM_ITU_CODING;
00609       qos->forward.qos_class = T_ATM_QOS_CLASS_1;
00610       qos->backward.qos_class = T_ATM_QOS_CLASS_1;
00611 
00612       popt = T_OPT_NEXTHDR (buf, info.options, popt);
00613     }
00614 
00615   
00616   *len = (char *) popt - buf;
00617 
00618   return buf;
00619 #else
00620   ACE_UNUSED_ARG (fd);
00621   ACE_UNUSED_ARG (rate);
00622   ACE_UNUSED_ARG (flag);
00623   ACE_UNUSED_ARG (len);
00624   return (0);
00625 #endif 
00626 }
00627 
00628 ACE_END_VERSIONED_NAMESPACE_DECL
00629 
00630 #endif 
00631