Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / QoS / QoS_Session_Impl.cpp
blobf552755488e3279035123aff90d3a6c22874f163
1 // QoS_Session_Impl.cpp
2 #include "ace/OS_NS_arpa_inet.h"
3 #include "ace/SOCK.h"
4 #include "QoS_Manager.h"
5 #include "QoS_Session_Impl.h"
6 #include "ace/Log_Category.h"
8 #if !defined (__ACE_INLINE__)
9 #include "QoS_Session_Impl.inl"
10 #endif /* __ACE_INLINE__ */
12 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
14 ACE_ALLOC_HOOK_DEFINE(ACE_QoS_Session_Impl)
16 ACE_END_VERSIONED_NAMESPACE_DECL
18 #if defined (ACE_HAS_RAPI)
19 #include "rapi_err.h"
21 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
23 int ACE_RAPI_Session::rsvp_error = 0;
25 // Call back function used by RAPI to report RSVP events. This
26 // function translates the RAPI QoS parameters into the more generic
27 // ACE_QoS parameters for the underlying RAPI session.
28 int
29 rsvp_callback (rapi_sid_t /* sid */,
30 rapi_eventinfo_t eventype,
31 int /* style_id */,
32 int errcode,
33 int errvalue,
34 sockaddr * errnode,
35 u_char /* errflags */,
36 int /* filter_spec_no */,
37 rapi_filter_t * /* filter_spec_list */,
38 int flow_spec_no,
39 rapi_flowspec_t *flow_spec_list,
40 int /* ad_spec_no */,
41 rapi_adspec_t * /* ad_spec_list */,
42 void *args
45 if (args == 0)
46 ACELIB_DEBUG ((LM_DEBUG,
47 "Argument in the call back function is null\n\n"));
49 ACE_QoS_Session *qos_session = (ACE_QoS_Session *) args;
51 qos_flowspecx_t *csxp = 0;
53 if (!flow_spec_list)
55 ACELIB_DEBUG ((LM_DEBUG,
56 "(%N|%l) Null flow_spec_list\n"));
58 else
60 // Extended Legacy format.
61 csxp = &flow_spec_list->specbody_qosx;
62 if(!csxp)
64 ACELIB_ERROR_RETURN ((LM_ERROR,
65 "(%N|%l) Null csxp\n"),
66 -1);
70 ACE_QoS ace_qos = qos_session->qos ();
72 switch(eventype)
74 case RAPI_PATH_EVENT:
76 ACELIB_DEBUG ((LM_DEBUG,
77 "RSVP PATH Event received\n"
78 "No. of TSpecs received : %d %d\n",
79 flow_spec_no, &flow_spec_list->len));
81 ACE_Flow_Spec *receiving_fs = 0;
83 if (flow_spec_no != 0)
85 ACE_NEW_RETURN (receiving_fs,
86 ACE_Flow_Spec,
87 -1);
89 ACE_NEW_RETURN (receiving_fs,
90 ACE_Flow_Spec ((u_long)csxp->xspec_r,
91 (u_long)csxp->xspec_b,
92 (u_long)csxp->xspec_p,
94 csxp->xspec_S,
96 csxp->xspec_M,
97 csxp->xspec_m,
98 25,
99 0),
100 -1);
102 ACELIB_DEBUG ((LM_DEBUG,
103 "\nTSpec :\n"
104 "\t Spec Type = %d\n"
105 "\t Rate = %f\n"
106 "\t Bucket = %f\n"
107 "\t Peak = %f\n"
108 "\t MPU = %d\n"
109 "\t MDU = %d\n"
110 "\t TTL = %d\n",
111 csxp->spec_type,
112 csxp->xspec_r,
113 csxp->xspec_b,
114 csxp->xspec_p,
115 csxp->xspec_m,
116 csxp->xspec_M,
117 25));
120 // Set the sending flowspec QoS of the given session.
121 ace_qos.receiving_flowspec (receiving_fs);
123 qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_PATH_EVENT);
125 break;
127 case RAPI_RESV_EVENT:
129 ACELIB_DEBUG ((LM_DEBUG,
130 "RSVP RESV Event received\n"
131 "No. of FlowSpecs received : %d\n",
132 flow_spec_no));
134 ACE_Flow_Spec *sending_flow = 0;
136 if (flow_spec_no != 0)
138 ACE_NEW_RETURN (sending_flow,
139 ACE_Flow_Spec,
140 -1);
142 // Choose based on the service type : [QOS_GUARANTEEDX/QOS_CNTR_LOAD].
143 switch (csxp->spec_type)
145 case QOS_GUARANTEEDX:
146 // Slack term in MICROSECONDS
147 sending_flow->delay_variation (csxp->xspec_S);
149 // @@How does the guaranteed rate parameter map to the ACE_Flow_Spec.
150 // Note there is no break !!
152 case QOS_CNTR_LOAD:
153 // qos_service_type.
154 sending_flow->service_type (csxp->spec_type);
155 // Token Bucket Average Rate (B/s)
156 sending_flow->token_rate ((u_long)csxp->xspec_r);
157 // Token Bucket Rate (B)
158 sending_flow->token_bucket_size ((u_long)csxp->xspec_b);
159 // Peak Data Rate (B/s)
160 sending_flow->peak_bandwidth ((u_long)csxp->xspec_p);
161 // Minimum Policed Unit (B)
162 sending_flow->minimum_policed_size (csxp->xspec_m);
163 // Max Packet Size (B)
164 sending_flow->max_sdu_size (csxp->xspec_M);
165 break;
167 default:
168 ACELIB_ERROR_RETURN ((LM_ERROR,
169 "(%N|%l) Unknown flowspec type: %u.\n", csxp->spec_type),
170 -1);
174 ace_qos.sending_flowspec (sending_flow);
175 qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_RESV_EVENT);
177 break;
179 case RAPI_PATH_ERROR:
181 ACELIB_DEBUG ((LM_DEBUG,
182 "PATH ERROR Event received\n"
183 "Code=%d Val=%d Node= %s\n",
184 errcode,
185 errvalue,
186 ACE_OS::inet_ntoa(((sockaddr_in *)errnode)->sin_addr)));
187 qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_PATH_ERROR);
189 break;
191 case RAPI_RESV_ERROR:
193 ACELIB_DEBUG ((LM_DEBUG,
194 "RESV ERROR Event received\n"
195 "Code=%d Val=%d Node= %s\n",
196 errcode,
197 errvalue,
198 ACE_OS::inet_ntoa(((sockaddr_in *)errnode)->sin_addr)));
199 qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_RESV_ERROR);
201 break;
203 case RAPI_RESV_CONFIRM:
205 ACELIB_DEBUG ((LM_DEBUG,
206 "RESV CONFIRM Event received\n"));
207 qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_RESV_CONFIRM);
209 break;
211 default:
212 ACELIB_DEBUG ((LM_DEBUG,
213 "Unknown RSVP Event Received\n"));
214 break;
217 // Set the updated ACE_QoS for the RSVP callback argument(QoS session).
218 qos_session->qos (ace_qos);
220 // @@ what is the meaning of the return value. RAPI docs don't say anything!
221 return 0;
224 // Constructor.
225 ACE_RAPI_Session::ACE_RAPI_Session ()
227 ACE_TRACE ("ACE_RAPI_Session::ACE_RAPI_Session");
228 //this->source_port (DEFAULT_SOURCE_SENDER_PORT);
229 ACE_NEW (this->src_addr_,
230 ACE_INET_Addr ("0"));
233 // Open a RAPI QoS session [dest IP, dest port, Protocol ID].
235 ACE_RAPI_Session::open (ACE_INET_Addr dest_addr,
236 ACE_Protocol_ID protocol_id)
238 char buf [BUFSIZ];
239 dest_addr.addr_to_string (buf,
240 BUFSIZ);
241 ACELIB_DEBUG ((LM_DEBUG,
242 "In RAPI SESSION OPEN %s\n",
243 buf));
245 this->dest_addr_ = dest_addr;
246 this->protocol_id_ = protocol_id;
248 // Open a RAPI session. Note "this" is being passed as an argument to
249 // the callback function. The callback function uses this argument to
250 // update the QoS of this session based on the RSVP event it receives.
252 if ((this->session_id_ = rapi_session((struct sockaddr *) dest_addr.get_addr (),
253 protocol_id,
255 rsvp_callback,
256 (void *) this,
257 &rsvp_error)) == NULL_SID)
258 ACELIB_ERROR_RETURN ((LM_ERROR,
259 "rapi_session () call fails. Error\n"),
260 -1);
261 else
262 ACELIB_DEBUG ((LM_DEBUG,
263 "rapi_session () call succeeds. "
264 "Session ID = %d\n",
265 this->session_id_));
267 return 0;
270 // Close the RAPI QoS Session.
272 ACE_RAPI_Session::close ()
274 this->rsvp_error = rapi_release(this->session_id_);
276 if (rsvp_error == 0)
277 ACELIB_ERROR_RETURN ((LM_ERROR,
278 "Can't release RSVP session:\n\t%s\n",
279 rapi_errlist[rsvp_error]),
280 -1);
281 else
282 ACELIB_DEBUG ((LM_DEBUG,
283 "rapi session with id %d released successfully.\n",
284 this->session_id_));
285 return 0;
288 //Get the most recent RSVP event that occurred
289 ACE_QoS_Session::RSVP_Event_Type
290 ACE_RAPI_Session::rsvp_event_type ()
292 return this->rsvp_event_type_;
295 //Set the most recent RSVP event that occurred
296 void
297 ACE_RAPI_Session::rsvp_event_type (ACE_QoS_Session::RSVP_Event_Type event_type)
299 this->rsvp_event_type_ = event_type;
303 ACE_RAPI_Session::qos (ACE_SOCK * /* socket */,
304 ACE_QoS_Manager * /* qos_manager */,
305 const ACE_QoS &ace_qos)
307 // If sender : call sending_qos ()
308 // If receiver : call receiving_qos ()
309 // If both : call sending_qos () and receiving_qos ()
311 if (this->flags_ != ACE_QOS_RECEIVER)
312 return this->sending_qos (ace_qos);
314 if (this->flags_ != ACE_QOS_SENDER)
315 return this->receiving_qos (ace_qos);
317 return 0;
320 // Set sending QoS for this RAPI session.
322 ACE_RAPI_Session::sending_qos (const ACE_QoS &ace_qos)
324 ACE_Flow_Spec *sending_flowspec = ace_qos.sending_flowspec ();
326 if (sending_flowspec == 0)
328 int result = rapi_sender (this->session_id_,
335 25);
336 if (result != 0)
337 ACELIB_ERROR_RETURN ((LM_ERROR,
338 "(%N|%l) rapi_sender error %d:\n\tPATH Generation can't be started\n",
339 result),
340 -1);
341 else
342 ACELIB_DEBUG ((LM_DEBUG,
343 "rapi_sender () call succeeds with PATH Tear!\n"));
345 return 0;
348 rapi_tspec_t *t_spec = this->init_tspec_simplified (*sending_flowspec);
349 if (t_spec == 0)
350 ACELIB_ERROR_RETURN ((LM_ERROR,
351 "(%N|%l) Error in translating from ACE Flow Spec to"
352 " RAPI TSpec\n"),
353 -1);
355 char buffer[BUFSIZ];
357 // This formats the t_spec in a visually intuitive char * that can
358 // be printed.
360 (void) rapi_fmt_tspec(t_spec, buffer, sizeof(buffer));
361 ACELIB_DEBUG ((LM_DEBUG,
362 "\nSender TSpec : %s\n",
363 buffer));
365 // Print out all the fields separately.
366 ACELIB_DEBUG ((LM_DEBUG,
367 "\nTSpec :\n"
368 "\t Spec Type = %d\n"
369 "\t Rate = %f\n"
370 "\t Bucket = %f\n"
371 "\t Peak = %f\n"
372 "\t MPU = %d\n"
373 "\t MDU = %d\n"
374 "\t TTL = %d\n",
375 t_spec->tspecbody_qosx.spec_type,
376 t_spec->tspecbody_qosx.xtspec_r,
377 t_spec->tspecbody_qosx.xtspec_b,
378 t_spec->tspecbody_qosx.xtspec_p,
379 t_spec->tspecbody_qosx.xtspec_m,
380 t_spec->tspecbody_qosx.xtspec_M,
381 sending_flowspec->ttl ()));
383 // This the source sender port.
384 // ACE_INET_Addr sender_addr (this->source_port ());
386 ACELIB_DEBUG ((LM_DEBUG,
387 "Making the rapi_sender () call\n"));
389 // Set the Sender TSpec for this QoS session.
392 int result = rapi_sender(this->session_id_,
394 (sockaddr *) this->src_addr_->get_addr (),
396 t_spec,
399 sending_flowspec->ttl ()) ;
402 int result = rapi_sender(this->session_id_,
404 (sockaddr *) sender_addr.get_addr (),
406 t_spec,
409 sending_flowspec->ttl ()) ;
411 if(result!= 0)
412 ACELIB_ERROR_RETURN ((LM_ERROR,
413 "(%N|%l) rapi_sender error %d:\n\tPATH Generation can't be started\n",
414 result),
415 -1);
416 else
417 ACELIB_DEBUG ((LM_DEBUG,
418 "rapi_sender () call succeeds !\n"));
419 return 0;
422 // Set receiving QoS for this RAPI session.
424 ACE_RAPI_Session::receiving_qos (const ACE_QoS &ace_qos)
426 ACE_Flow_Spec *receiving_flowspec = ace_qos.receiving_flowspec ();
427 if (receiving_flowspec == 0)
429 if (rapi_reserve(this->session_id_,
431 // Setting the RAPI_REQ_CONFIRM flag requests confirmation
432 // of the resevation, by means of a confirmation upcall of
433 // type RAPI_RESV_CONFIRM.
434 // (sockaddr *)receiver_addr.get_addr (),
436 RAPI_RSTYLE_WILDCARD,
437 // This applies the flowspec to all the senders. Given this,
438 // @@I am passing the filter_spec to be null, hoping this will work.
443 // The filter spec is NULL. This should work since the RSTYLE is
444 // WILDCARD.
446 0) == -1)
447 ACELIB_ERROR_RETURN ((LM_ERROR,
448 "(%N|%l)rapi_reserve () error:\n\tRESV Generation can't be started\n"),
449 -1);
450 else
451 ACELIB_DEBUG ((LM_DEBUG,
452 "rapi_reserve () for RESV Tear call succeeds\n"));
454 return 0;
458 rapi_flowspec_t *flow_spec = init_flowspec_simplified (*receiving_flowspec);
460 if (flow_spec == 0)
461 ACELIB_ERROR_RETURN ((LM_ERROR,
462 "(%N|%l) Error in translating from ACE Flow Spec to"
463 " RAPI FlowSpec\n"),
464 -1);
466 char buffer[BUFSIZ];
468 // This formats the flow_spec in a visually intuitive char * that can
469 // be printed.
470 (void)rapi_fmt_flowspec(flow_spec, buffer, sizeof(buffer));
471 ACELIB_DEBUG ((LM_DEBUG,
472 "\nReceiver FlowSpec : %s\n",
473 buffer));
475 // Print out all the fields separately.
476 ACELIB_DEBUG ((LM_DEBUG,
477 "\nFlowSpec :\n"
478 "\t Spec Type = %d\n"
479 "\t Rate = %f\n"
480 "\t Bucket = %f\n"
481 "\t Peak = %f\n"
482 "\t MPU = %d\n"
483 "\t MDU = %d\n",
484 flow_spec->specbody_qosx.spec_type,
485 flow_spec->specbody_qosx.xspec_r,
486 flow_spec->specbody_qosx.xspec_b,
487 flow_spec->specbody_qosx.xspec_p,
488 flow_spec->specbody_qosx.xspec_m,
489 flow_spec->specbody_qosx.xspec_M));
491 sockaddr_in Receiver_host;
493 Receiver_host.sin_addr.s_addr = INADDR_ANY;
495 // Set the Receiver FlowSpec for this QoS session.
496 // @@The filter style is hardcoded to WildCard. This can be changed later.
497 if (rapi_reserve(this->session_id_,
498 RAPI_REQ_CONFIRM,
499 // Setting the RAPI_REQ_CONFIRM flag requests confirmation
500 // of the resevation, by means of a confirmation upcall of
501 // type RAPI_RESV_CONFIRM.
502 // (sockaddr *)receiver_addr.get_addr (),
503 (sockaddr *)&Receiver_host,
504 RAPI_RSTYLE_WILDCARD,
505 // This applies the flowspec to all the senders. Given this,
506 // @@I am passing the filter_spec to be null, hoping this will work.
511 // The filter spec is NULL. This should work since the RSTYLE is
512 // WILDCARD.
514 flow_spec) == -1)
515 ACELIB_ERROR_RETURN ((LM_ERROR,
516 "rapi_reserve () error:\n\tRESV Generation can't be started\n"),
517 -1);
518 else
519 ACELIB_DEBUG ((LM_DEBUG,
520 "rapi_reserve () call succeeds\n"));
522 return 0;
526 ACE_RAPI_Session::update_qos ()
528 // Update the session QoS Parameters based on the RSVP Event Received.
529 if ((rsvp_error = rapi_dispatch ()) != 0)
530 ACELIB_ERROR_RETURN ((LM_ERROR,
531 "Error in rapi_dispatch () : %s\n",
532 rapi_errlist[rsvp_error]),
533 -1);
534 return 0;
537 // Construct a simplified RAPI Sender TSpec object
538 // from an ACE_Flow_Spec. Note the form of the TSpec is
539 // simplified as against the full bodied IntServ version.
541 rapi_tspec_t *
542 ACE_RAPI_Session::init_tspec_simplified (const ACE_Flow_Spec &flow_spec)
544 rapi_tspec_t *t_spec;
546 ACE_NEW_RETURN (t_spec,
547 rapi_tspec_t,
550 qos_tspecx_t *ctxp = &(t_spec->tspecbody_qosx);
552 // There may be some type incompatibility here.
553 // Note the types of the LHS are float32_t, uint32_t etc.
555 ctxp->spec_type = flow_spec.service_type ();//QOS_TSPEC;
556 ctxp->xtspec_r = flow_spec.token_rate (); // Token Rate (B/s)
557 ctxp->xtspec_b = flow_spec.token_bucket_size (); // Token Bucket Depth (B)
558 ctxp->xtspec_p = flow_spec.peak_bandwidth (); // Peak Data Rate (B/s)
559 ctxp->xtspec_m = flow_spec.minimum_policed_size (); // Minimum policed unit.
560 ctxp->xtspec_M = flow_spec.max_sdu_size(); // Maximum SDU size.
561 t_spec->len = sizeof(rapi_hdr_t) + sizeof(qos_tspecx_t);
562 t_spec->form = RAPI_TSPECTYPE_Simplified;
564 return (t_spec);
568 // Construct a simplified RAPI flowspec object from ACE_Flow_Spec.
569 // Note the form of the FlowSpec is simplified as against the
570 // full bodied IntServ version.
572 rapi_flowspec_t *
573 ACE_RAPI_Session::init_flowspec_simplified(const ACE_Flow_Spec &flow_spec)
575 rapi_flowspec_t *flowsp;
576 ACE_NEW_RETURN (flowsp,
577 rapi_flowspec_t,
580 // Extended Legacy format.
581 qos_flowspecx_t *csxp = &flowsp->specbody_qosx;
583 // Choose based on the service type : [QOS_GUARANTEEDX/QOS_CNTR_LOAD].
585 switch (flow_spec.service_type ())
587 case QOS_GUARANTEEDX:
588 csxp->xspec_R = 0 ; // Guaranteed Rate B/s. @@How does this map to the
589 // ACE Flow Spec Parameters.
591 csxp->xspec_S = flow_spec.delay_variation () ; // Slack term in MICROSECONDS
593 // Note there is no break !!
595 case QOS_CNTR_LOAD:
596 csxp->spec_type = flow_spec.service_type (); // qos_service_type
597 csxp->xspec_r = flow_spec.token_rate (); // Token Bucket Average Rate (B/s)
598 csxp->xspec_b = flow_spec.token_bucket_size (); // Token Bucket Rate (B)
599 csxp->xspec_p = flow_spec.peak_bandwidth (); // Peak Data Rate (B/s)
600 csxp->xspec_m = flow_spec.minimum_policed_size (); // Minimum Policed Unit (B)
602 csxp->xspec_M = flow_spec.max_sdu_size(); // Max Packet Size (B)
604 flowsp->form = RAPI_FLOWSTYPE_Simplified;
605 break;
607 default:
608 ACELIB_ERROR_RETURN ((LM_ERROR,
609 "(%N|%l) Unknown flowspec type: %u\n",flow_spec.service_type () ),
613 flowsp->len = sizeof(rapi_flowspec_t);
614 return flowsp;
617 ACE_END_VERSIONED_NAMESPACE_DECL
619 #endif /* ACE_HAS_RAPI */
621 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
623 // This is a GQoS session ID generator.
624 int ACE_GQoS_Session::GQoS_session_id = 0;
626 // Constructor.
627 ACE_GQoS_Session::ACE_GQoS_Session ()
629 ACE_TRACE ("ACE_GQoS_Session::ACE_GQoS_Session");
632 // Open a GQoS session [dest IP, dest port, Protocol ID].
634 ACE_GQoS_Session::open (ACE_INET_Addr dest_addr,
635 ACE_Protocol_ID protocol_id)
637 this->dest_addr_ = dest_addr;
638 this->protocol_id_ = protocol_id;
640 this->session_id_ = GQoS_session_id++;
642 return 0;
645 // Close the GQoS Session.
647 ACE_GQoS_Session::close ()
649 // TBD.
650 return 0;
653 // Set the QoS for this GQoS session.
655 ACE_GQoS_Session::qos (ACE_SOCK *socket,
656 ACE_QoS_Manager *qos_manager,
657 const ACE_QoS &ace_qos)
659 // Confirm if the current session is one of the QoS sessions
660 // subscribed to by the given socket.
662 if (qos_manager->qos_session_set ().find (this) == -1)
663 ACELIB_ERROR_RETURN ((LM_ERROR,
664 ACE_TEXT ("This QoS session was not subscribed to")
665 ACE_TEXT (" by the socket\n")),
666 -1);
668 // Set the QOS according to the supplied ACE_QoS. The I/O control
669 // code used under the hood is SIO_SET_QOS.
671 u_long ret_bytes = 0;
673 ACE_QoS qos = ace_qos;
674 if (ACE_OS::ioctl (socket->get_handle (),
675 ACE_SIO_SET_QOS,
676 qos,
677 &ret_bytes) == -1)
678 ACELIB_ERROR_RETURN ((LM_ERROR,
679 ACE_TEXT ("Error in Qos set ACE_OS::ioctl() %d\n"),
680 ret_bytes),
681 -1);
682 else
683 ACELIB_DEBUG ((LM_DEBUG,
684 ACE_TEXT ("Setting QoS with ACE_OS::ioctl () succeeds\n")));
686 return 0;
690 ACE_GQoS_Session::update_qos ()
692 // WSAIoctl (GET_QOS) call goes here...
693 return 0;
696 //Get the most recent RSVP event that occurred
697 ACE_QoS_Session::RSVP_Event_Type
698 ACE_GQoS_Session::rsvp_event_type ()
700 return this->rsvp_event_type_;
703 //Set the most recent RSVP event that occurred
704 void
705 ACE_GQoS_Session::rsvp_event_type (ACE_QoS_Session::RSVP_Event_Type event_type)
707 this->rsvp_event_type_ = event_type;
710 ACE_END_VERSIONED_NAMESPACE_DECL