3 ==================================================================================
4 Copyright (c) 2020 Nokia
5 Copyright (c) 2020 AT&T Intellectual Property.
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
11 http://www.apache.org/licenses/LICENSE-2.0
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 ==================================================================================
22 Mnemonic: rmr_dump.cpp
23 Abstract: This is a sample xapp which will behave somewhat like tcpdump
24 as it receives rmr messages. The list of message types which should
25 be processed are given on the command line, following any flag
26 options (e.g. -p port). Any of those messages received are reported
27 on by the application. The verbosity level may be used to increase
28 the amount of detail given for the tracked messages.
30 This writes to the TTY which is slow, so do not expect it to be able
31 to process and report on a high rate of messages. Also, forwarded
32 messages will reach the intended target, however if the target
33 attempts to send a response the response will come back to THIS
34 application, and not the message origination; this cannot be a bit
35 of middleware in it's current form.
38 Author: E. Scott Daniels
40 Caution: This example code is pulled directly into one or more of the documents
41 (starting from the "start-example" tag below. Use caution with
42 line lengths and contents because of the requirement that this
43 be documentation as well as working code.
50 #include "ricxfcpp/xapp.hpp"
53 Information that the callback needs outside
54 of what is given to it via parms on a call
58 int vlevel; // verbosity level
59 bool forward; // if true, message is forwarded
60 int stats_freq; // header/stats after n messages
61 std::atomic<long> pcount; // messages processed
62 std::atomic<long> icount; // messages ignored
63 std::atomic<int> hdr; // number of messages before next header
66 // ----------------------------------------------------------------------
71 void dump( unsigned const char* buf, int len ) {
76 fprintf( stdout, "<RD> 0000 | " );
78 for( i = 0; i < len; i++ ) {
79 cheater[j++] = isprint( buf[i] ) ? buf[i] : '.';
80 fprintf( stdout, "%02x ", buf[i] );
84 fprintf( stdout, " | %s\n<RD> %04x | ", cheater, i+1 );
92 fprintf( stdout, " " );
95 fprintf( stdout, " | %s\n", cheater );
100 generate stats when the hdr count reaches 0. Only one active
101 thread will ever see it be exactly 0, so this is thread safe.
103 void stats( cb_info_t& cbi ) {
104 int curv; // current stat trigger value
108 if( curv == 0 ) { // stats when we reach 0
109 fprintf( stdout, "ignored: %ld processed: %ld\n",
110 cbi.icount.load(), cbi.pcount.load() );
111 if( cbi.vlevel > 0 ) {
112 fprintf( stdout, "\n %5s %5s %2s %5s\n",
113 "MTYPE", "SUBID", "ST", "PLLEN" );
116 cbi.hdr = cbi.stats_freq; // reset must be last
120 void cb1( xapp::Message& mbuf, int mtype, int subid, int len,
121 xapp::Msg_component payload, void* data ) {
125 if( (cbi = (cb_info_t *) data) == NULL ) {
130 stats( *cbi ); // gen stats & header if needed
132 if( cbi->vlevel > 0 ) {
133 fprintf( stdout, "<RD> %-5d %-5d %02d %-5d \n",
134 mtype, subid, mbuf.Get_state(), len );
136 if( cbi->vlevel > 1 ) {
137 dump( payload.get(), len > 64 ? 64 : len );
142 // forward with no change to len or payload
143 mbuf.Send_msg( xapp::Message::NO_CHANGE, NULL );
148 registered as the default callback; it counts the
149 messages that we aren't giving details about.
151 void cbd( xapp::Message& mbuf, int mtype, int subid, int len,
152 xapp::Msg_component payload, void* data ) {
155 if( (cbi = (cb_info_t *) data) == NULL ) {
163 // forward with no change to len or payload
164 mbuf.Send_msg( xapp::Message::NO_CHANGE, NULL );
168 int main( int argc, char** argv ) {
169 std::unique_ptr<Xapp> x;
170 char* port = (char *) "4560";
171 int ai = 1; // arg processing index
173 int ncb = 0; // number of callbacks registered
177 cbi = (cb_info_t *) malloc( sizeof( *cbi ) );
180 cbi->stats_freq = 10;
183 // very simple flag parsing (no error/bounds checking)
185 if( argv[ai][0] != '-' ) { // break on first non-flag
189 // very simple arg parsing; each must be separate -x -y not -xy.
190 switch( argv[ai][1] ) {
191 case 'f': // enable packet forwarding
195 case 'p': // define port
200 case 's': // stats frequency
201 cbi->stats_freq = atoi( argv[ai+1] );
202 if( cbi->stats_freq < 5 ) { // enforce sanity
208 case 't': // thread count
209 nthreads = atoi( argv[ai+1] );
216 case 'v': // simple verbose bump
220 case 'V': // explicit verbose level
221 cbi->vlevel = atoi( argv[ai+1] );
226 fprintf( stderr, "unrecognised option: %s\n", argv[ai] );
227 fprintf( stderr, "usage: %s [-f] [-p port] "
228 "[-s stats-freq] [-t thread-count] "
229 "[-v | -V n] msg-type1 ... msg-typen\n",
231 fprintf( stderr, "\tstats frequency is based on # of messages received\n" );
232 fprintf( stderr, "\tverbose levels (-V) 0 counts only, "
233 "1 message info 2 payload dump\n" );
240 cbi->hdr = cbi->stats_freq;
241 fprintf( stderr, "<RD> listening on port: %s\n", port );
243 // create xapp, wait for route table if forwarding
244 x = std::unique_ptr<Xapp>( new Xapp( port, cbi->forward ) );
246 // register callback for each type on the command line
248 mtype = atoi( argv[ai] );
250 fprintf( stderr, "<RD> capturing messages for type %d\n", mtype );
251 x->Add_msg_cb( mtype, cb1, cbi );
256 fprintf( stderr, "<RD> no message types specified on the command line\n" );
260 x->Add_msg_cb( x->DEFAULT_CALLBACK, cbd, cbi ); // register default cb
262 fprintf( stderr, "<RD> starting driver\n" );
265 // return from run() is not expected, but some compilers might
266 // compilain if there isn't a return value here.