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"));
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!
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
)
240 dest_addr
.addr_to_string (buf
,
242 ACELIB_DEBUG ((LM_DEBUG
,
243 "In RAPI SESSION OPEN %s\n",
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 (),
258 &rsvp_error
)) == NULL_SID
)
259 ACELIB_ERROR_RETURN ((LM_ERROR
,
260 "rapi_session () call fails. Error\n"),
263 ACELIB_DEBUG ((LM_DEBUG
,
264 "rapi_session () call succeeds. "
271 // Close the RAPI QoS Session.
273 ACE_RAPI_Session::close (void)
275 this->rsvp_error
= rapi_release(this->session_id_
);
278 ACELIB_ERROR_RETURN ((LM_ERROR
,
279 "Can't release RSVP session:\n\t%s\n",
280 rapi_errlist
[rsvp_error
]),
283 ACELIB_DEBUG ((LM_DEBUG
,
284 "rapi session with id %d released successfully.\n",
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
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
);
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_
,
339 ACELIB_ERROR_RETURN ((LM_ERROR
,
340 "(%N|%l) rapi_sender error %d:\n\tPATH Generation can't be started\n",
344 ACELIB_DEBUG ((LM_DEBUG
,
345 "rapi_sender () call succeeds with PATH Tear!\n"));
350 rapi_tspec_t
*t_spec
= this->init_tspec_simplified (*sending_flowspec
);
352 ACELIB_ERROR_RETURN ((LM_ERROR
,
353 "(%N|%l) Error in translating from ACE Flow Spec to"
359 // This formats the t_spec in a visually intuitive char * that can
362 (void) rapi_fmt_tspec(t_spec
, buffer
, sizeof(buffer
));
363 ACELIB_DEBUG ((LM_DEBUG
,
364 "\nSender TSpec : %s\n",
367 // Print out all the fields separately.
368 ACELIB_DEBUG ((LM_DEBUG
,
370 "\t Spec Type = %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 (),
401 sending_flowspec
->ttl ()) ;
404 int result = rapi_sender(this->session_id_,
406 (sockaddr *) sender_addr.get_addr (),
411 sending_flowspec->ttl ()) ;
414 ACELIB_ERROR_RETURN ((LM_ERROR
,
415 "(%N|%l) rapi_sender error %d:\n\tPATH Generation can't be started\n",
419 ACELIB_DEBUG ((LM_DEBUG
,
420 "rapi_sender () call succeeds !\n"));
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
450 ACELIB_ERROR_RETURN ((LM_ERROR
,
451 "(%N|%l)rapi_reserve () error:\n\tRESV Generation can't be started\n"),
454 ACELIB_DEBUG ((LM_DEBUG
,
455 "rapi_reserve () for RESV Tear call succeeds\n"));
461 rapi_flowspec_t
*flow_spec
= init_flowspec_simplified (*receiving_flowspec
);
464 ACELIB_ERROR_RETURN ((LM_ERROR
,
465 "(%N|%l) Error in translating from ACE Flow Spec to"
471 // This formats the flow_spec in a visually intuitive char * that can
473 (void)rapi_fmt_flowspec(flow_spec
, buffer
, sizeof(buffer
));
474 ACELIB_DEBUG ((LM_DEBUG
,
475 "\nReceiver FlowSpec : %s\n",
478 // Print out all the fields separately.
479 ACELIB_DEBUG ((LM_DEBUG
,
481 "\t Spec Type = %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_
,
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
518 ACELIB_ERROR_RETURN ((LM_ERROR
,
519 "rapi_reserve () error:\n\tRESV Generation can't be started\n"),
522 ACELIB_DEBUG ((LM_DEBUG
,
523 "rapi_reserve () call succeeds\n"));
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
]),
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.
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
,
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
;
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.
576 ACE_RAPI_Session::init_flowspec_simplified(const ACE_Flow_Spec
&flow_spec
)
578 rapi_flowspec_t
*flowsp
;
579 ACE_NEW_RETURN (flowsp
,
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 !!
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
;
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
);
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;
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
++;
648 // Close the GQoS Session.
650 ACE_GQoS_Session::close (void)
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")),
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 (),
682 ACELIB_ERROR_RETURN ((LM_ERROR
,
683 ACE_TEXT ("Error in Qos set ACE_OS::ioctl() %d\n"),
687 ACELIB_DEBUG ((LM_DEBUG
,
688 ACE_TEXT ("Setting QoS with ACE_OS::ioctl () succeeds\n")));
694 ACE_GQoS_Session::update_qos (void)
696 // WSAIoctl (GET_QOS) call goes here...
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
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