summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2022-04-04 10:10:58 -0700
committerDamjan Marion <dmarion@me.com>2022-04-04 19:08:47 +0000
commit0dde17573261d32e50d86ea584bc70f0796e0f46 (patch)
tree4bc0e0220867630beb1fc6ca1fefe38447c50cbe
parentc7ef4f391bcfb515af52cfcf9c71bb6b16006fc1 (diff)
session: use session layer rpc for evts sent to main
Fix race with connects for iperf3 udp test. Type: fix Signed-off-by: Florin Coras <fcoras@cisco.com> Change-Id: Ief725b80047911e87ba24736dc0a60aa8bcdac50
-rw-r--r--src/vnet/session/session_node.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c
index 89c8ab0c891..89017f00bee 100644
--- a/src/vnet/session/session_node.c
+++ b/src/vnet/session/session_node.c
@@ -30,7 +30,7 @@ static inline void
session_wrk_send_evt_to_main (session_worker_t *wrk, session_evt_elt_t *elt)
{
session_evt_elt_t *he;
- u32 thread_index;
+ uword thread_index;
u8 is_empty;
thread_index = wrk->vm->thread_index;
@@ -38,8 +38,8 @@ session_wrk_send_evt_to_main (session_worker_t *wrk, session_evt_elt_t *elt)
is_empty = clib_llist_is_empty (wrk->event_elts, evt_list, he);
clib_llist_add_tail (wrk->event_elts, evt_list, elt, he);
if (is_empty)
- vlib_rpc_call_main_thread (session_wrk_handle_evts_main_rpc,
- (u8 *) &thread_index, sizeof (thread_index));
+ session_send_rpc_evt_to_thread (0, session_wrk_handle_evts_main_rpc,
+ uword_to_pointer (thread_index, void *));
}
#define app_check_thread_and_barrier(_wrk, _elt) \
@@ -777,11 +777,13 @@ void
session_wrk_handle_evts_main_rpc (void *args)
{
session_evt_elt_t *he, *elt, *next;
+ vlib_main_t *vm = vlib_get_main ();
session_worker_t *fwrk;
u32 thread_index;
- ASSERT (vlib_thread_is_main_w_barrier ());
- thread_index = *(u32 *) args;
+ vlib_worker_thread_barrier_sync (vm);
+
+ thread_index = pointer_to_uword (args);
fwrk = session_main_get_worker (thread_index);
he = clib_llist_elt (fwrk->event_elts, fwrk->evts_pending_main);
@@ -817,6 +819,8 @@ session_wrk_handle_evts_main_rpc (void *args)
clib_llist_put (fwrk->event_elts, elt);
elt = next;
}
+
+ vlib_worker_thread_barrier_release (vm);
}
vlib_node_registration_t session_queue_node;
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
#!/usr/bin/env python
#
# Copyright (c) 2016 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
from string import Template

import dto_gen
import util

jvpp_facade_callback_template = Template("""
package $base_package.$future_package;

/**
 * <p>Async facade callback setting values to future objects
 * <br>It was generated by jvpp_future_facade_gen.py based on $inputfile
 * <br>(python representation of vpe.api generated by vppapigen).
 */
public final class FutureJVppFacadeCallback implements $base_package.$callback_package.JVppGlobalCallback {

    private final java.util.Map<java.lang.Integer, java.util.concurrent.CompletableFuture<? extends $base_package.$dto_package.JVppReply<?>>> requests;

    public FutureJVppFacadeCallback(final java.util.Map<java.lang.Integer, java.util.concurrent.CompletableFuture<? extends $base_package.$dto_package.JVppReply<?>>> requestMap) {
        this.requests = requestMap;
    }

$methods
}
""")

jvpp_facade_callback_method_template = Template("""
    @Override
    @SuppressWarnings("unchecked")
    public void on$callback_dto($base_package.$dto_package.$callback_dto reply) {
        final java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<?>> completableFuture;

        synchronized(requests) {
            completableFuture = (java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<?>>) requests.get(reply.context);
        }

        if(completableFuture != null) {
            if(reply.retval < 0) {
                completableFuture.completeExceptionally(new Exception("Invocation of " + $base_package.$dto_package.$callback_dto.class
                    + " failed with value " + reply.retval));
            } else {
                completableFuture.complete(reply);
            }

            synchronized(requests) {
                requests.remove(reply.context);
            }
        }
    }
""")

# TODO reuse common parts with generic method callback
jvpp_facade_control_ping_method_template = Template("""
    @Override
    @SuppressWarnings("unchecked")
    public void on$callback_dto($base_package.$dto_package.$callback_dto reply) {
        final java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<?>> completableFuture;

        synchronized(requests) {
            completableFuture = (java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<?>>) requests.get(reply.context);
        }

        if(completableFuture != null) {
            // Finish dump call
            if (completableFuture instanceof $base_package.$future_package.FutureJVppFacade.CompletableDumpFuture) {
                completableFuture.complete((($base_package.$future_package.FutureJVppFacade.CompletableDumpFuture) completableFuture).getReplyDump());
                // Remove future mapped to dump call context id
                synchronized(requests) {
                    requests.remove((($base_package.$future_package.FutureJVppFacade.CompletableDumpFuture) completableFuture).getContextId());
                }
            } else {
                if(reply.retval < 0) {
                    completableFuture.completeExceptionally(new Exception("Invocation of " + $base_package.$dto_package.$callback_dto.class
                        + " failed with value " + reply.retval));
                } else {
                    completableFuture.complete(reply);
                }
            }

            synchronized(requests) {
                requests.remove(reply.context);
            }
        }
    }
""")

jvpp_facade_details_callback_method_template = Template("""
    @Override
    @SuppressWarnings("unchecked")
    public void on$callback_dto($base_package.$dto_package.$callback_dto reply) {
        final FutureJVppFacade.CompletableDumpFuture<$base_package.$dto_package.$callback_dto_reply_dump> completableFuture;

        synchronized(requests) {
            completableFuture = ($base_package.$future_package.FutureJVppFacade.CompletableDumpFuture<$base_package.$dto_package.$callback_dto_reply_dump>) requests.get(reply.context);
        }

        if(completableFuture != null) {
            $base_package.$dto_package.$callback_dto_reply_dump replyDump = completableFuture.getReplyDump();
            if(replyDump == null) {
                replyDump = new $base_package.$dto_package.$callback_dto_reply_dump();
                completableFuture.setReplyDump(replyDump);
            }

            replyDump.$callback_dto_field.add(reply);
        }
    }
""")


def generate_jvpp(func_list, base_package, dto_package, callback_package, future_facade_package, inputfile):
    """ Generates JVpp interface and JNI implementation """
    print "Generating JVpp future facade"

    if not os.path.exists(future_facade_package):
        raise Exception("%s folder is missing" % future_facade_package)

    methods = []
    methods_impl = []
    callbacks = []
    for func in func_list:

        if util.is_notification(func['name']) or util.is_ignored(func['name']):
            # TODO handle notifications
            continue

        camel_case_name_with_suffix = util.underscore_to_camelcase_upper(func['name'])
        if not util.is_reply(camel_case_name_with_suffix):
            continue

        camel_case_method_name = util.underscore_to_camelcase(func['name'])
        camel_case_request_method_name = util.remove_reply_suffix(util.underscore_to_camelcase(func['name']))
        if util.is_details(camel_case_name_with_suffix):
            camel_case_reply_name = get_standard_dump_reply_name(util.underscore_to_camelcase_upper(func['name']),
                                                                   func['name'])
            callbacks.append(jvpp_facade_details_callback_method_template.substitute(base_package=base_package,
                                                                                     dto_package=dto_package,
                                                                                     callback_dto=camel_case_name_with_suffix,
                                                                                     callback_dto_field=camel_case_method_name,
                                                                                     callback_dto_reply_dump=camel_case_reply_name + dto_gen.dump_dto_suffix,
                                                                                     future_package=future_facade_package))

            methods.append(future_jvpp_method_template.substitute(base_package=base_package,
                                                                  dto_package=dto_package,
                                                                  method_name=camel_case_request_method_name +
                                                                              util.underscore_to_camelcase_upper(util.dump_suffix),
                                                                  reply_name=camel_case_reply_name + dto_gen.dump_dto_suffix,
                                                                  request_name=util.remove_reply_suffix(camel_case_reply_name) +
                                                                               util.underscore_to_camelcase_upper(util.dump_suffix)))
            methods_impl.append(future_jvpp_method_impl_template.substitute(base_package=base_package,
                                                                            dto_package=dto_package,
                                                                            method_name=camel_case_request_method_name +
                                                                                        util.underscore_to_camelcase_upper(util.dump_suffix),
                                                                            reply_name=camel_case_reply_name + dto_gen.dump_dto_suffix,
                                                                            request_name=util.remove_reply_suffix(camel_case_reply_name) +
                                                                                         util.underscore_to_camelcase_upper(util.dump_suffix)))
        else:
            request_name = util.underscore_to_camelcase_upper(util.unconventional_naming_rep_req[func['name']]) \
                if func['name'] in util.unconventional_naming_rep_req else util.remove_reply_suffix(camel_case_name_with_suffix)

            methods.append(future_jvpp_method_template.substitute(base_package=base_package,
                                                                  dto_package=dto_package,
                                                                  method_name=camel_case_request_method_name,
                                                                  reply_name=camel_case_name_with_suffix,
                                                                  request_name=request_name))
            methods_impl.append(future_jvpp_method_impl_template.substitute(base_package=base_package,
                                                                            dto_package=dto_package,
                                                                            method_name=camel_case_request_method_name,
                                                                            reply_name=camel_case_name_with_suffix,
                                                                            request_name=request_name))

            # Callback handler is a bit special and a different template has to be used
            if util.is_control_ping(camel_case_name_with_suffix):
                callbacks.append(jvpp_facade_control_ping_method_template.substitute(base_package=base_package,
                                                                                     dto_package=dto_package,
                                                                                     callback_dto=camel_case_name_with_suffix,
                                                                                     future_package=future_facade_package))
            else:
                callbacks.append(jvpp_facade_callback_method_template.substitute(base_package=base_package,
                                                                                 dto_package=dto_package,
                                                                                 callback_dto=camel_case_name_with_suffix))

    jvpp_file = open(os.path.join(future_facade_package, "FutureJVppFacadeCallback.java"), 'w')
    jvpp_file.write(jvpp_facade_callback_template.substitute(inputfile=inputfile,
                                                             base_package=base_package,
                                                             dto_package=dto_package,
                                                             callback_package=callback_package,
                                                             methods="".join(callbacks),
                                                             future_package=future_facade_package))
    jvpp_file.flush()
    jvpp_file.close()

    jvpp_file = open(os.path.join(future_facade_package, "FutureJVpp.java"), 'w')
    jvpp_file.write(future_jvpp_template.substitute(inputfile=inputfile,
                                                    base_package=base_package,
                                                    methods="".join(methods),
                                                    future_package=future_facade_package))
    jvpp_file.flush()
    jvpp_file.close()

    jvpp_file = open(os.path.join(future_facade_package, "FutureJVppFacade.java"), 'w')
    jvpp_file.write(future_jvpp_facade_template.substitute(inputfile=inputfile,
                                                           base_package=base_package,
                                                           dto_package=dto_package,
                                                           methods="".join(methods_impl),
                                                           future_package=future_facade_package))
    jvpp_file.flush()
    jvpp_file.close()


future_jvpp_template = Template('''
package $base_package.$future_package;

/**
 * <p>Async facade extension adding specific methods for each request invocation
 * <br>It was generated by jvpp_future_facade_gen.py based on $inputfile
 * <br>(python representation of vpe.api generated by vppapigen).
 */
public interface FutureJVpp extends FutureJVppInvoker {
$methods
}
''')

future_jvpp_method_template = Template('''
    java.util.concurrent.CompletionStage<$base_package.$dto_package.$reply_name> $method_name($base_package.$dto_package.$request_name request);
''')


future_jvpp_facade_template = Template('''
package $base_package.$future_package;

/**
 * <p>Implementation of FutureJVpp based on FutureJVppInvokerFacade
 * <br>It was generated by jvpp_future_facade_gen.py based on $inputfile
 * <br>(python representation of vpe.api generated by vppapigen).
 */
public class FutureJVppFacade extends FutureJVppInvokerFacade implements FutureJVpp {

    public FutureJVppFacade(final $base_package.JVpp jvpp,
                            final java.util.Map<Integer, java.util.concurrent.CompletableFuture<? extends $base_package.$dto_package.JVppReply<?>>> requestMap) {
        super(jvpp, requestMap);
    }
$methods
}
''')

future_jvpp_method_impl_template = Template('''
    @Override
    public java.util.concurrent.CompletionStage<$base_package.$dto_package.$reply_name> $method_name($base_package.$dto_package.$request_name request) {
        return send(request);
    }
''')

# Returns request name or special one from unconventional_naming_rep_req map
def get_standard_dump_reply_name(camel_case_dto_name, func_name):
    # FIXME this is a hotfix for sub-details callbacks
    # FIXME also for L2FibTableEntry
    # It's all because unclear mapping between
    #  request -> reply,
    #  dump -> reply, details,
    #  notification_start -> reply, notifications

    # vpe.api needs to be "standardized" so we can parse the information and create maps before generating java code
    suffix = func_name.split("_")[-1]
    return util.underscore_to_camelcase_upper(
        util.unconventional_naming_rep_req[func_name]) + util.underscore_to_camelcase_upper(suffix) if func_name in util.unconventional_naming_rep_req \
        else camel_case_dto_name