1 // QoS_Session_Impl.cpp
2 #include "ace/OS_NS_arpa_inet.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)
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.
29 rsvp_callback (rapi_sid_t
/* sid */,
30 rapi_eventinfo_t eventype
,
35 u_char
/* errflags */,
36 int /* filter_spec_no */,
37 rapi_filter_t
* /* filter_spec_list */,
39 rapi_flowspec_t
*flow_spec_list
,
41 rapi_adspec_t
* /* ad_spec_list */,
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;
55 ACELIB_DEBUG ((LM_DEBUG
,
56 "(%N|%l) Null flow_spec_list\n"));
60 // Extended Legacy format.
61 csxp
= &flow_spec_list
->specbody_qosx
;
64 ACELIB_ERROR_RETURN ((LM_ERROR
,
65 "(%N|%l) Null csxp\n"),
70 ACE_QoS ace_qos
= qos_session
->qos ();
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
,
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
,
102 ACELIB_DEBUG ((LM_DEBUG
,
104 "\t Spec Type = %d\n"
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
);
127 case RAPI_RESV_EVENT
:
129 ACELIB_DEBUG ((LM_DEBUG
,
130 "RSVP RESV Event received\n"
131 "No. of FlowSpecs received : %d\n",
134 ACE_Flow_Spec
*sending_flow
= 0;
136 if (flow_spec_no
!= 0)
138 ACE_NEW_RETURN (sending_flow
,
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 !!
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
);
168 ACELIB_ERROR_RETURN ((LM_ERROR
,
169 "(%N|%l) Unknown flowspec type: %u.\n", csxp
->spec_type
),
174 ace_qos
.sending_flowspec (sending_flow
);
175 qos_session
->rsvp_event_type (ACE_QoS_Session::RSVP_RESV_EVENT
);
179 case RAPI_PATH_ERROR
:
181 ACELIB_DEBUG ((LM_DEBUG
,
182 "PATH ERROR Event received\n"
183 "Code=%d Val=%d Node= %s\n",
186 ACE_OS::inet_ntoa(((sockaddr_in
*)errnode
)->sin_addr
)));
187 qos_session
->rsvp_event_type (ACE_QoS_Session::RSVP_PATH_ERROR
);
191 case RAPI_RESV_ERROR
:
193 ACELIB_DEBUG ((LM_DEBUG
,
194 "RESV ERROR Event received\n"
195 "Code=%d Val=%d Node= %s\n",
198 ACE_OS::inet_ntoa(((sockaddr_in
*)errnode
)->sin_addr
)));
199 qos_session
->rsvp_event_type (ACE_QoS_Session::RSVP_RESV_ERROR
);
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
);
212 ACELIB_DEBUG ((LM_DEBUG
,
213 "Unknown RSVP Event Received\n"));
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!
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
)
239 dest_addr
.addr_to_string (buf
,
241 ACELIB_DEBUG ((LM_DEBUG
,
242 "In RAPI SESSION OPEN %s\n",
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 (),
257 &rsvp_error
)) == NULL_SID
)
258 ACELIB_ERROR_RETURN ((LM_ERROR
,
259 "rapi_session () call fails. Error\n"),
262 ACELIB_DEBUG ((LM_DEBUG
,
263 "rapi_session () call succeeds. "
270 // Close the RAPI QoS Session.
272 ACE_RAPI_Session::close ()
274 this->rsvp_error
= rapi_release(this->session_id_
);
277 ACELIB_ERROR_RETURN ((LM_ERROR
,
278 "Can't release RSVP session:\n\t%s\n",
279 rapi_errlist
[rsvp_error
]),
282 ACELIB_DEBUG ((LM_DEBUG
,
283 "rapi session with id %d released successfully.\n",
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
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
);
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_
,
337 ACELIB_ERROR_RETURN ((LM_ERROR
,
338 "(%N|%l) rapi_sender error %d:\n\tPATH Generation can't be started\n",
342 ACELIB_DEBUG ((LM_DEBUG
,
343 "rapi_sender () call succeeds with PATH Tear!\n"));
348 rapi_tspec_t
*t_spec
= this->init_tspec_simplified (*sending_flowspec
);
350 ACELIB_ERROR_RETURN ((LM_ERROR
,
351 "(%N|%l) Error in translating from ACE Flow Spec to"
357 // This formats the t_spec in a visually intuitive char * that can
360 (void) rapi_fmt_tspec(t_spec
, buffer
, sizeof(buffer
));
361 ACELIB_DEBUG ((LM_DEBUG
,
362 "\nSender TSpec : %s\n",
365 // Print out all the fields separately.
366 ACELIB_DEBUG ((LM_DEBUG
,
368 "\t Spec Type = %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 (),
399 sending_flowspec
->ttl ()) ;
402 int result = rapi_sender(this->session_id_,
404 (sockaddr *) sender_addr.get_addr (),
409 sending_flowspec->ttl ()) ;
412 ACELIB_ERROR_RETURN ((LM_ERROR
,
413 "(%N|%l) rapi_sender error %d:\n\tPATH Generation can't be started\n",
417 ACELIB_DEBUG ((LM_DEBUG
,
418 "rapi_sender () call succeeds !\n"));
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
447 ACELIB_ERROR_RETURN ((LM_ERROR
,
448 "(%N|%l)rapi_reserve () error:\n\tRESV Generation can't be started\n"),
451 ACELIB_DEBUG ((LM_DEBUG
,
452 "rapi_reserve () for RESV Tear call succeeds\n"));
458 rapi_flowspec_t
*flow_spec
= init_flowspec_simplified (*receiving_flowspec
);
461 ACELIB_ERROR_RETURN ((LM_ERROR
,
462 "(%N|%l) Error in translating from ACE Flow Spec to"
468 // This formats the flow_spec in a visually intuitive char * that can
470 (void)rapi_fmt_flowspec(flow_spec
, buffer
, sizeof(buffer
));
471 ACELIB_DEBUG ((LM_DEBUG
,
472 "\nReceiver FlowSpec : %s\n",
475 // Print out all the fields separately.
476 ACELIB_DEBUG ((LM_DEBUG
,
478 "\t Spec Type = %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_
,
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
515 ACELIB_ERROR_RETURN ((LM_ERROR
,
516 "rapi_reserve () error:\n\tRESV Generation can't be started\n"),
519 ACELIB_DEBUG ((LM_DEBUG
,
520 "rapi_reserve () call succeeds\n"));
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
]),
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.
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
,
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
;
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.
573 ACE_RAPI_Session::init_flowspec_simplified(const ACE_Flow_Spec
&flow_spec
)
575 rapi_flowspec_t
*flowsp
;
576 ACE_NEW_RETURN (flowsp
,
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 !!
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
;
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
);
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;
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
++;
645 // Close the GQoS Session.
647 ACE_GQoS_Session::close ()
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")),
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 (),
678 ACELIB_ERROR_RETURN ((LM_ERROR
,
679 ACE_TEXT ("Error in Qos set ACE_OS::ioctl() %d\n"),
683 ACELIB_DEBUG ((LM_DEBUG
,
684 ACE_TEXT ("Setting QoS with ACE_OS::ioctl () succeeds\n")));
690 ACE_GQoS_Session::update_qos ()
692 // WSAIoctl (GET_QOS) call goes here...
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
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