vpp/vpp-japi/japi/vppjni.h
Robert Varga 81d99acf45 Cache jclass/jmethodID/jfieldID references
This patch introduces an initialization framework, which tracks required
references to Java classes and methods.

It works by declaring classes and their constructor signatures, which
are linked into a singly-linked list when the .so initializers are run.
Once JNI_OnLoad() is invoked, this list is walked and all classes and
their initializers are resolved. These are then used while the library
remains loaded. Once JNI_OnUnload() is called, global references are
released, so we can cleanly unload.

The class declaration results in static utility objects being emitted in
the scope of the declaration, hence to allocate an object or an array of
objects is done via simple calls.

Change-Id: I41984c13756339364dbcbf0144b947627e8e4fe1
Signed-off-by: Robert Varga <nite@hq.sk>
2016-01-30 22:20:30 +01:00

308 lines
7.5 KiB
C

/*
* Copyright (c) 2015 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.
*/
#ifndef __included_vppjni_h__
#define __included_vppjni_h__
#include <vnet/vnet.h>
#include <vnet/ip/ip.h>
#include <vnet/api_errno.h>
#include <vlibapi/api.h>
#include <vlibmemory/api.h>
#include <jni.h>
#include <japi/vppjni_bridge_domain.h>
typedef struct {
u8 * name;
u32 value;
} name_sort_t;
typedef struct {
u8 valid; // used in a vector of sw_interface_details_t
u8 interface_name[64];
u32 sw_if_index;
u32 sup_sw_if_index;
u32 l2_address_length;
u8 l2_address[8];
u8 admin_up_down;
u8 link_up_down;
u8 link_duplex;
u8 link_speed;
u32 sub_id;
u8 sub_dot1ad;
u8 sub_number_of_tags;
u16 sub_outer_vlan_id;
u16 sub_inner_vlan_id;
u8 sub_exact_match;
u8 sub_default;
u8 sub_outer_vlan_id_any;
u8 sub_inner_vlan_id_any;
u32 vtr_op;
u32 vtr_push_dot1q;
u32 vtr_tag1;
u32 vtr_tag2;
} sw_interface_details_t;
typedef struct {
u8 * interface_name;
u32 sw_if_index;
/*
* Subinterface ID. A number 0-N to uniquely identify
* this subinterface under the super interface
*/
u32 sub_id;
/* 0 = dot1q, 1=dot1ad */
u8 sub_dot1ad;
/* Number of tags 0-2 */
u8 sub_number_of_tags;
u16 sub_outer_vlan_id;
u16 sub_inner_vlan_id;
u8 sub_exact_match;
u8 sub_default;
u8 sub_outer_vlan_id_any;
u8 sub_inner_vlan_id_any;
/* vlan tag rewrite */
u32 vtr_op;
u32 vtr_push_dot1q;
u32 vtr_tag1;
u32 vtr_tag2;
} sw_interface_subif_t;
typedef struct {
u8 *desc;
} sw_if_config_t;
typedef struct {
u32 ip;
u8 prefix_length;
} ipv4_address_t;
typedef struct {
u8 ip[16];
u8 prefix_length;
} ipv6_address_t;
typedef struct {
u64 ip4;
u64 ip6;
u64 unicast;
u64 multicast;
u64 broadcast;
u64 discard;
u64 fifo_full;
u64 error;
u64 unknown_proto;
u64 miss;
} packet_counters_t;
typedef struct {
u64 octets;
packet_counters_t pkts;
} if_counters_t;
typedef struct {
u8 valid;
u32 sw_if_index;
if_counters_t rx;
if_counters_t tx;
} sw_interface_stats_t;
typedef struct {
u32 src_address;
u32 dst_address;
u32 encap_vrf_id;
u32 vni;
u32 decap_next_index;
} vxlan_tunnel_details_t;
typedef struct {
/* Context IDs */
volatile u32 context_id_sent;
volatile u32 context_id_received;
/* Spinlock */
volatile u32 lock;
u32 tag;
/* To recycle pseudo-synchronous message code from vpp_api_test... */
volatile u32 result_ready;
volatile i32 retval;
volatile u8 *shmem_result;
/* thread cleanup */
pthread_key_t cleanup_rx_thread_key;
/* attachment of rx thread to java thread */
JNIEnv *jenv;
JavaVM *jvm;
uword *callback_hash; // map context_id => jobject
uword *ping_hash; // map ping context_id => msg type called
/* Timestamp */
clib_time_t clib_time;
/* connected indication */
u8 is_connected;
/* context -> non-trivial reply hash */
uword * reply_hash;
u32 saved_reply_count;
/* interface name map */
uword * sw_if_index_by_interface_name;
/* interface counters */
sw_interface_stats_t * sw_if_stats_by_sw_if_index;
/* interface table */
sw_interface_details_t * sw_if_table;
uword * sw_if_config_by_sw_if_index;
/* interface indices of responses to one sw_if_dump request */
u8 collect_indices;
u32 * sw_if_dump_if_indices;
/* program name, build_dir, version */
u8 program_name[32];
u8 build_directory[256];
u8 version[32];
u8 build_date[32];
/* subinterface table */
sw_interface_subif_t * sw_if_subif_table;
/* used in ip_address_dump request and response handling */
ipv4_address_t *ipv4_addresses;
ipv6_address_t *ipv6_addresses;
u8 is_ipv6;
/* used in vxlan_tunnel_dump request and response handling */
vxlan_tunnel_details_t *vxlan_tunnel_details;
/* main heap */
u8 * heap;
/* convenience */
unix_shared_memory_queue_t * vl_input_queue;
api_main_t * api_main;
u32 my_client_index;
vjbd_main_t vjbd_main;
} vppjni_main_t;
vppjni_main_t vppjni_main __attribute__((aligned (64)));
static inline u32 vppjni_get_context_id (vppjni_main_t * jm)
{
u32 my_context_id;
my_context_id = __sync_add_and_fetch (&jm->context_id_sent, 1);
return my_context_id;
}
static inline void vppjni_lock (vppjni_main_t * jm, u32 tag)
{
while (__sync_lock_test_and_set (&jm->lock, 1))
;
jm->tag = tag;
}
static inline void vppjni_unlock (vppjni_main_t * jm)
{
jm->tag = 0;
CLIB_MEMORY_BARRIER();
jm->lock = 0;
}
static inline f64 vppjni_time_now (vppjni_main_t *jm)
{
return clib_time_now (&jm->clib_time);
}
static inline int vppjni_sanity_check (vppjni_main_t * jm)
{
if (!jm->is_connected)
return VNET_API_ERROR_NOT_CONNECTED;
return 0;
}
#define __PACKED(x) x __attribute__((packed))
typedef __PACKED(struct _vl_api_generic_reply {
u16 _vl_msg_id;
u32 context;
i32 retval;
u8 data[0];
}) vl_api_generic_reply_t;
void vl_api_generic_reply_handler (vl_api_generic_reply_t *mp);
/* M: construct, but don't yet send a message */
#define M(T,t) \
do { \
jm->result_ready = 0; \
mp = vl_msg_api_alloc(sizeof(*mp)); \
memset (mp, 0, sizeof (*mp)); \
mp->_vl_msg_id = ntohs (VL_API_##T); \
mp->client_index = jm->my_client_index; \
} while(0);
#define M2(T,t,n) \
do { \
jm->result_ready = 0; \
mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \
memset (mp, 0, sizeof (*mp)); \
mp->_vl_msg_id = ntohs (VL_API_##T); \
mp->client_index = jm->my_client_index; \
} while(0);
/* S: send a message */
#define S (vl_msg_api_send_shmem (jm->vl_input_queue, (u8 *)&mp))
/* W: wait for results, with timeout */
#define W \
do { \
timeout = vppjni_time_now (jm) + 1.0; \
\
while (vppjni_time_now (jm) < timeout) { \
if (jm->result_ready == 1) { \
return (jm->retval); \
} \
} \
return -99; \
} while(0);
/* WNR: wait for results, with timeout (without returning) */
#define WNR \
do { \
timeout = vppjni_time_now (jm) + 1.0; \
\
rv = -99; \
while (vppjni_time_now (jm) < timeout) { \
if (jm->result_ready == 1) { \
rv = (jm->retval); \
break; \
} \
} \
} while(0);
#endif /* __included_vppjni_h__ */