summaryrefslogtreecommitdiffstats
path: root/src/vnet/session
diff options
context:
space:
mode:
authorNathan Skrzypczak <nathan.skrzypczak@gmail.com>2021-08-10 15:05:29 +0200
committerNeale Ranns <neale@graphiant.com>2021-08-13 18:29:23 +0000
commit2a1783fd6ae7e17c994010fca414c180eb48bc40 (patch)
treec7f12d0894ccd57a3098da77414338cb394c5efc /src/vnet/session
parent8034a36a9cedc95f6762bf0a07f6617d0bf69bfe (diff)
ip: punt redirect add nh in api
Type: feature Change-Id: Ia970f444ba2f38b7a42ea94942c906f1b541511b Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
Diffstat (limited to 'src/vnet/session')
0 files changed, 0 insertions, 0 deletions
n110' href='#n110'>110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
/*
 * 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.
 */

package io.fd.vpp.jvpp;

import static java.util.Objects.requireNonNull;

import io.fd.vpp.jvpp.callback.ControlPingCallback;
import io.fd.vpp.jvpp.callback.JVppCallback;
import io.fd.vpp.jvpp.dto.ControlPingReply;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Default implementation of JVppRegistry.
 */
public final class JVppRegistryImpl implements JVppRegistry, ControlPingCallback {

    private static final Logger LOG = Logger.getLogger(JVppRegistryImpl.class.getName());

    private final VppJNIConnection connection;
    // Unguarded concurrent map, no race conditions expected on top of that
    private final Map<String, JVppCallback> pluginRegistry;
    // Guarded by self
    private final Map<Integer, ControlPingCallback> pingCalls;

    public JVppRegistryImpl(final String clientName) throws IOException {
        connection = new VppJNIConnection(clientName);
        connection.connect();
        pluginRegistry = new ConcurrentHashMap<>();
        pingCalls = new HashMap<>();
    }

    public JVppRegistryImpl(final String clientName, final String shmPrefix) throws IOException {
        connection = new VppJNIConnection(clientName, shmPrefix);
        connection.connect();
        pluginRegistry = new ConcurrentHashMap<>();
        pingCalls = new HashMap<>();
    }

    @Override
    public VppConnection getConnection() {
        return connection;
    }

    @Override
    public void register(final JVpp jvpp, final JVppCallback callback) {
        requireNonNull(jvpp, "jvpp should not be null");
        requireNonNull(callback, "Callback should not be null");
        final String name = jvpp.getClass().getName();
        if (pluginRegistry.containsKey(name)) {
            throw new IllegalArgumentException(
                String.format("Callback for plugin %s was already registered", name));
        }
        jvpp.init(this, callback, connection.getConnectionInfo().queueAddress,
            connection.getConnectionInfo().clientIndex);
        pluginRegistry.put(name, callback);
    }

    @Override
    public void unregister(final String name) {
        requireNonNull(name, "Plugin name should not be null");
        final JVppCallback previous = pluginRegistry.remove(name);
        assertPluginWasRegistered(name, previous);
    }

    @Override
    public JVppCallback get(final String name) {
        requireNonNull(name, "Plugin name should not be null");
        JVppCallback value = pluginRegistry.get(name);
        assertPluginWasRegistered(name, value);
        return value;
    }

    private native int controlPing0() throws VppInvocationException;

    @Override
    public int controlPing(final Class<? extends JVpp> clazz) throws VppInvocationException {
        connection.checkActive();
        final String name = clazz.getName();

        final ControlPingCallback callback = (ControlPingCallback) pluginRegistry.get(clazz.getName());
        assertPluginWasRegistered(name, callback);

        synchronized (pingCalls) {
            int context = controlPing0();
            if (context < 0) {
                throw new VppInvocationException("controlPing", context);
            }

            pingCalls.put(context, callback);
            return context;
        }
    }

    @Override
    public void onControlPingReply(final ControlPingReply reply) {
        final ControlPingCallback callback;
        synchronized (pingCalls) {
            callback = pingCalls.remove(reply.context);
            if (callback == null) {
                LOG.log(Level.WARNING, "No callback was registered for reply context=" + reply.context + " Contexts waiting="
                    + pingCalls.keySet());
                return;
            }
        }
        // pass the reply to the callback registered by the ping caller
        callback.onControlPingReply(reply);
    }

    @Override
    public void onError(final VppCallbackException ex) {
        final int ctxId = ex.getCtxId();
        final ControlPingCallback callback;

        synchronized (pingCalls) {
            callback = pingCalls.get(ctxId);
        }
        if (callback == null) {
            LOG.log(Level.WARNING, "No callback was registered for reply id={0} ", ctxId);
            return;
        }
        // pass the error to the callback registered by the ping caller
        callback.onError(ex);
    }

    private static void assertPluginWasRegistered(final String name, final JVppCallback value) {
        if (value == null) {
            throw new IllegalArgumentException(String.format("Callback for plugin %s is not registered", name));
        }
    }

    @Override
    public void close() throws Exception {
        connection.close();
    }
}