Revert to Current Include Style
[ACE_TAO.git] / ACE / ace / QoS / QoS_Session_Impl.cpp
blob28d42bc0b8218f7939ceeeece1e9b3427fb48897
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;
218 // Set the updated ACE_QoS for the RSVP callback argument(QoS session).
219 qos_session->qos (ace_qos);
221 // @@ what is the meaning of the return value. RAPI docs don't say anything!
222 return 0;
225 // Constructor.
226 ACE_RAPI_Session::ACE_RAPI_Session (void)
228 ACE_TRACE ("ACE_RAPI_Session::ACE_RAPI_Session");
229 //this->source_port (DEFAULT_SOURCE_SENDER_PORT);
230 ACE_NEW (this->src_addr_,
231 ACE_INET_Addr ("0"));
234 // Open a RAPI QoS session [dest IP, dest port, Protocol ID].
236 ACE_RAPI_Session::open (ACE_INET_Addr dest_addr,
237 ACE_Protocol_ID protocol_id)
239 char buf [BUFSIZ];
240 dest_addr.addr_to_string (buf,
241 BUFSIZ);
242 ACELIB_DEBUG ((LM_DEBUG,
243 "In RAPI SESSION OPEN %s\n",
244 buf));
246 this->dest_addr_ = dest_addr;
247 this->protocol_id_ = protocol_id;
249 // Open a RAPI session. Note "this" is being passed as an argument to
250 // the callback function. The callback function uses this argument to
251 // update the QoS of this session based on the RSVP event it receives.
253 if ((this->session_id_ = rapi_session((struct sockaddr *) dest_addr.get_addr (),
254 protocol_id,
256 rsvp_callback,
257 (void *) this,
258 &rsvp_error)) == NULL_SID)
259 ACELIB_ERROR_RETURN ((LM_ERROR,
260 "rapi_session () call fails. Error\n"),
261 -1);
262 else
263 ACELIB_DEBUG ((LM_DEBUG,
264 "rapi_session () call succeeds. "
265 "Session ID = %d\n",
266 this->session_id_));
268 return 0;
271 // Close the RAPI QoS Session.
273 ACE_RAPI_Session::close (void)
275 this->rsvp_error = rapi_release(this->session_id_);
277 if (rsvp_error == 0)
278 ACELIB_ERROR_RETURN ((LM_ERROR,
279 "Can't release RSVP session:\n\t%s\n",
280 rapi_errlist[rsvp_error]),
281 -1);
282 else
283 ACELIB_DEBUG ((LM_DEBUG,
284 "rapi session with id %d released successfully.\n",
285 this->session_id_));
286 return 0;
289 //Get the most recent RSVP event that occurred
290 ACE_QoS_Session::RSVP_Event_Type
291 ACE_RAPI_Session::rsvp_event_type (void)
293 return this->rsvp_event_type_;
296 //Set the most recent RSVP event that occurred
297 void
298 ACE_RAPI_Session::rsvp_event_type (ACE_QoS_Session::RSVP_Event_Type event_type)
300 this->rsvp_event_type_ = event_type;
304 ACE_RAPI_Session::qos (ACE_SOCK * /* socket */,
305 ACE_QoS_Manager * /* qos_manager */,
306 const ACE_QoS &ace_qos)
309 // If sender : call sending_qos ()
310 // If receiver : call receiving_qos ()
311 // If both : call sending_qos () and receiving_qos ()
313 if (this->flags_ != ACE_QOS_RECEIVER)
314 return this->sending_qos (ace_qos);
316 if (this->flags_ != ACE_QOS_SENDER)
317 return this->receiving_qos (ace_qos);
319 return 0;
322 // Set sending QoS for this RAPI session.
324 ACE_RAPI_Session::sending_qos (const ACE_QoS &ace_qos)
326 ACE_Flow_Spec *sending_flowspec = ace_qos.sending_flowspec ();
328 if (sending_flowspec == 0)
330 int result = rapi_sender (this->session_id_,
337 25);
338 if (result != 0)
339 ACELIB_ERROR_RETURN ((LM_ERROR,
340 "(%N|%l) rapi_sender error %d:\n\tPATH Generation can't be started\n",
341 result),
342 -1);
343 else
344 ACELIB_DEBUG ((LM_DEBUG,
345 "rapi_sender () call succeeds with PATH Tear!\n"));
347 return 0;
350 rapi_tspec_t *t_spec = this->init_tspec_simplified (*sending_flowspec);
351 if (t_spec == 0)
352 ACELIB_ERROR_RETURN ((LM_ERROR,
353 "(%N|%l) Error in translating from ACE Flow Spec to"
354 " RAPI TSpec\n"),
355 -1);
357 char buffer[BUFSIZ];
359 // This formats the t_spec in a visually intuitive char * that can
360 // be printed.
362 (void) rapi_fmt_tspec(t_spec, buffer, sizeof(buffer));
363 ACELIB_DEBUG ((LM_DEBUG,
364 "\nSender TSpec : %s\n",
365 buffer));
367 // Print out all the fields separately.
368 ACELIB_DEBUG ((LM_DEBUG,
369 "\nTSpec :\n"
370 "\t Spec Type = %d\n"
371 "\t Rate = %f\n"
372 "\t Bucket = %f\n"
373 "\t Peak = %f\n"
374 "\t MPU = %d\n"
375 "\t MDU = %d\n"
376 "\t TTL = %d\n",
377 t_spec->tspecbody_qosx.spec_type,
378 t_spec->tspecbody_qosx.xtspec_r,
379 t_spec->tspecbody_qosx.xtspec_b,
380 t_spec->tspecbody_qosx.xtspec_p,
381 t_spec->tspecbody_qosx.xtspec_m,
382 t_spec->tspecbody_qosx.xtspec_M,
383 sending_flowspec->ttl ()));
385 // This the source sender port.
386 // ACE_INET_Addr sender_addr (this->source_port ());
388 ACELIB_DEBUG ((LM_DEBUG,
389 "Making the rapi_sender () call\n"));
391 // Set the Sender TSpec for this QoS session.
394 int result = rapi_sender(this->session_id_,
396 (sockaddr *) this->src_addr_->get_addr (),
398 t_spec,
401 sending_flowspec->ttl ()) ;
404 int result = rapi_sender(this->session_id_,
406 (sockaddr *) sender_addr.get_addr (),
408 t_spec,
411 sending_flowspec->ttl ()) ;
413 if(result!= 0)
414 ACELIB_ERROR_RETURN ((LM_ERROR,
415 "(%N|%l) rapi_sender error %d:\n\tPATH Generation can't be started\n",
416 result),
417 -1);
418 else
419 ACELIB_DEBUG ((LM_DEBUG,
420 "rapi_sender () call succeeds !\n"));
421 return 0;
424 // Set receiving QoS for this RAPI session.
426 ACE_RAPI_Session::receiving_qos (const ACE_QoS &ace_qos)
429 ACE_Flow_Spec *receiving_flowspec = ace_qos.receiving_flowspec ();
430 if (receiving_flowspec == 0)
432 if (rapi_reserve(this->session_id_,
434 // Setting the RAPI_REQ_CONFIRM flag requests confirmation
435 // of the resevation, by means of a confirmation upcall of
436 // type RAPI_RESV_CONFIRM.
437 // (sockaddr *)receiver_addr.get_addr (),
439 RAPI_RSTYLE_WILDCARD,
440 // This applies the flowspec to all the senders. Given this,
441 // @@I am passing the filter_spec to be null, hoping this will work.
446 // The filter spec is NULL. This should work since the RSTYLE is
447 // WILDCARD.
449 0) == -1)
450 ACELIB_ERROR_RETURN ((LM_ERROR,
451 "(%N|%l)rapi_reserve () error:\n\tRESV Generation can't be started\n"),
452 -1);
453 else
454 ACELIB_DEBUG ((LM_DEBUG,
455 "rapi_reserve () for RESV Tear call succeeds\n"));
457 return 0;
461 rapi_flowspec_t *flow_spec = init_flowspec_simplified (*receiving_flowspec);
463 if (flow_spec == 0)
464 ACELIB_ERROR_RETURN ((LM_ERROR,
465 "(%N|%l) Error in translating from ACE Flow Spec to"
466 " RAPI FlowSpec\n"),
467 -1);
469 char buffer[BUFSIZ];
471 // This formats the flow_spec in a visually intuitive char * that can
472 // be printed.
473 (void)rapi_fmt_flowspec(flow_spec, buffer, sizeof(buffer));
474 ACELIB_DEBUG ((LM_DEBUG,
475 "\nReceiver FlowSpec : %s\n",
476 buffer));
478 // Print out all the fields separately.
479 ACELIB_DEBUG ((LM_DEBUG,
480 "\nFlowSpec :\n"
481 "\t Spec Type = %d\n"
482 "\t Rate = %f\n"
483 "\t Bucket = %f\n"
484 "\t Peak = %f\n"
485 "\t MPU = %d\n"
486 "\t MDU = %d\n",
487 flow_spec->specbody_qosx.spec_type,
488 flow_spec->specbody_qosx.xspec_r,
489 flow_spec->specbody_qosx.xspec_b,
490 flow_spec->specbody_qosx.xspec_p,
491 flow_spec->specbody_qosx.xspec_m,
492 flow_spec->specbody_qosx.xspec_M));
494 sockaddr_in Receiver_host;
496 Receiver_host.sin_addr.s_addr = INADDR_ANY;
498 // Set the Receiver FlowSpec for this QoS session.
499 // @@The filter style is hardcoded to WildCard. This can be changed later.
500 if (rapi_reserve(this->session_id_,
501 RAPI_REQ_CONFIRM,
502 // Setting the RAPI_REQ_CONFIRM flag requests confirmation
503 // of the resevation, by means of a confirmation upcall of
504 // type RAPI_RESV_CONFIRM.
505 // (sockaddr *)receiver_addr.get_addr (),
506 (sockaddr *)&Receiver_host,
507 RAPI_RSTYLE_WILDCARD,
508 // This applies the flowspec to all the senders. Given this,
509 // @@I am passing the filter_spec to be null, hoping this will work.
514 // The filter spec is NULL. This should work since the RSTYLE is
515 // WILDCARD.
517 flow_spec) == -1)
518 ACELIB_ERROR_RETURN ((LM_ERROR,
519 "rapi_reserve () error:\n\tRESV Generation can't be started\n"),
520 -1);
521 else
522 ACELIB_DEBUG ((LM_DEBUG,
523 "rapi_reserve () call succeeds\n"));
525 return 0;
529 ACE_RAPI_Session::update_qos (void)
531 // Update the session QoS Parameters based on the RSVP Event Received.
532 if ((rsvp_error = rapi_dispatch ()) != 0)
533 ACELIB_ERROR_RETURN ((LM_ERROR,
534 "Error in rapi_dispatch () : %s\n",
535 rapi_errlist[rsvp_error]),
536 -1);
537 return 0;
540 // Construct a simplified RAPI Sender TSpec object
541 // from an ACE_Flow_Spec. Note the form of the TSpec is
542 // simplified as against the full bodied IntServ version.
544 rapi_tspec_t *
545 ACE_RAPI_Session::init_tspec_simplified (const ACE_Flow_Spec &flow_spec)
547 rapi_tspec_t *t_spec;
549 ACE_NEW_RETURN (t_spec,
550 rapi_tspec_t,
553 qos_tspecx_t *ctxp = &(t_spec->tspecbody_qosx);
555 // There may be some type incompatibility here.
556 // Note the types of the LHS are float32_t, uint32_t etc.
558 ctxp->spec_type = flow_spec.service_type ();//QOS_TSPEC;
559 ctxp->xtspec_r = flow_spec.token_rate (); // Token Rate (B/s)
560 ctxp->xtspec_b = flow_spec.token_bucket_size (); // Token Bucket Depth (B)
561 ctxp->xtspec_p = flow_spec.peak_bandwidth (); // Peak Data Rate (B/s)
562 ctxp->xtspec_m = flow_spec.minimum_policed_size (); // Minimum policed unit.
563 ctxp->xtspec_M = flow_spec.max_sdu_size(); // Maximum SDU size.
564 t_spec->len = sizeof(rapi_hdr_t) + sizeof(qos_tspecx_t);
565 t_spec->form = RAPI_TSPECTYPE_Simplified;
567 return (t_spec);
571 // Construct a simplified RAPI flowspec object from ACE_Flow_Spec.
572 // Note the form of the FlowSpec is simplified as against the
573 // full bodied IntServ version.
575 rapi_flowspec_t *
576 ACE_RAPI_Session::init_flowspec_simplified(const ACE_Flow_Spec &flow_spec)
578 rapi_flowspec_t *flowsp;
579 ACE_NEW_RETURN (flowsp,
580 rapi_flowspec_t,
583 // Extended Legacy format.
584 qos_flowspecx_t *csxp = &flowsp->specbody_qosx;
586 // Choose based on the service type : [QOS_GUARANTEEDX/QOS_CNTR_LOAD].
588 switch (flow_spec.service_type ())
590 case QOS_GUARANTEEDX:
591 csxp->xspec_R = 0 ; // Guaranteed Rate B/s. @@How does this map to the
592 // ACE Flow Spec Parameters.
594 csxp->xspec_S = flow_spec.delay_variation () ; // Slack term in MICROSECONDS
596 // Note there is no break !!
598 case QOS_CNTR_LOAD:
599 csxp->spec_type = flow_spec.service_type (); // qos_service_type
600 csxp->xspec_r = flow_spec.token_rate (); // Token Bucket Average Rate (B/s)
601 csxp->xspec_b = flow_spec.token_bucket_size (); // Token Bucket Rate (B)
602 csxp->xspec_p = flow_spec.peak_bandwidth (); // Peak Data Rate (B/s)
603 csxp->xspec_m = flow_spec.minimum_policed_size (); // Minimum Policed Unit (B)
605 csxp->xspec_M = flow_spec.max_sdu_size(); // Max Packet Size (B)
607 flowsp->form = RAPI_FLOWSTYPE_Simplified;
608 break;
610 default:
611 ACELIB_ERROR_RETURN ((LM_ERROR,
612 "(%N|%l) Unknown flowspec type: %u\n",flow_spec.service_type () ),
616 flowsp->len = sizeof(rapi_flowspec_t);
617 return flowsp;
620 ACE_END_VERSIONED_NAMESPACE_DECL
622 #endif /* ACE_HAS_RAPI */
624 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
626 // This is a GQoS session ID generator.
627 int ACE_GQoS_Session::GQoS_session_id = 0;
629 // Constructor.
630 ACE_GQoS_Session::ACE_GQoS_Session (void)
632 ACE_TRACE ("ACE_GQoS_Session::ACE_GQoS_Session");
635 // Open a GQoS session [dest IP, dest port, Protocol ID].
637 ACE_GQoS_Session::open (ACE_INET_Addr dest_addr,
638 ACE_Protocol_ID protocol_id)
640 this->dest_addr_ = dest_addr;
641 this->protocol_id_ = protocol_id;
643 this->session_id_ = GQoS_session_id++;
645 return 0;
648 // Close the GQoS Session.
650 ACE_GQoS_Session::close (void)
652 // TBD.
653 return 0;
656 // Set the QoS for this GQoS session.
658 ACE_GQoS_Session::qos (ACE_SOCK *socket,
659 ACE_QoS_Manager *qos_manager,
660 const ACE_QoS &ace_qos)
663 // Confirm if the current session is one of the QoS sessions
664 // subscribed to by the given socket.
666 if (qos_manager->qos_session_set ().find (this) == -1)
667 ACELIB_ERROR_RETURN ((LM_ERROR,
668 ACE_TEXT ("This QoS session was not subscribed to")
669 ACE_TEXT (" by the socket\n")),
670 -1);
672 // Set the QOS according to the supplied ACE_QoS. The I/O control
673 // code used under the hood is SIO_SET_QOS.
675 u_long ret_bytes = 0;
677 ACE_QoS qos = ace_qos;
678 if (ACE_OS::ioctl (socket->get_handle (),
679 ACE_SIO_SET_QOS,
680 qos,
681 &ret_bytes) == -1)
682 ACELIB_ERROR_RETURN ((LM_ERROR,
683 ACE_TEXT ("Error in Qos set ACE_OS::ioctl() %d\n"),
684 ret_bytes),
685 -1);
686 else
687 ACELIB_DEBUG ((LM_DEBUG,
688 ACE_TEXT ("Setting QoS with ACE_OS::ioctl () succeeds\n")));
690 return 0;
694 ACE_GQoS_Session::update_qos (void)
696 // WSAIoctl (GET_QOS) call goes here...
697 return 0;
700 //Get the most recent RSVP event that occurred
701 ACE_QoS_Session::RSVP_Event_Type
702 ACE_GQoS_Session::rsvp_event_type (void)
704 return this->rsvp_event_type_;
707 //Set the most recent RSVP event that occurred
708 void
709 ACE_GQoS_Session::rsvp_event_type (ACE_QoS_Session::RSVP_Event_Type event_type)
711 this->rsvp_event_type_ = event_type;
714 ACE_END_VERSIONED_NAMESPACE_DECL