/* Reconfigures ovsdb-server based on information in the database. */ static void reconfigure_from_db(struct ovsdb_jsonrpc_server *jsonrpc, const struct ovsdb *db, struct shash *remotes) { struct shash resolved_remotes; struct shash_node *node; /* Configure remotes. */ shash_init(&resolved_remotes); SHASH_FOR_EACH (node, remotes) { const char *name = node->name; if (!strncmp(name, "db:", 3)) { query_db_remotes(name, db, &resolved_remotes); } else { shash_add_once(&resolved_remotes, name, NULL); } } ovsdb_jsonrpc_server_set_remotes(jsonrpc, &resolved_remotes); shash_destroy(&resolved_remotes); #if HAVE_OPENSSL /* Configure SSL. */ stream_ssl_set_key_and_cert(query_db_string(db, private_key_file), query_db_string(db, certificate_file)); stream_ssl_set_ca_cert_file(query_db_string(db, ca_cert_file), bootstrap_ca_cert); #endif }
static void create_port_groups(struct shash *port_groups) { shash_init(port_groups); static const char *const pg1[] = { "lsp1", "lsp2", "lsp3", }; static const char *const pg2[] = { NULL }; expr_const_sets_add(port_groups, "pg1", pg1, 3, false); expr_const_sets_add(port_groups, "pg_empty", pg2, 0, false); }
static void create_addr_sets(struct shash *addr_sets) { shash_init(addr_sets); static const char *const addrs1[] = { "10.0.0.1", "10.0.0.2", "10.0.0.3", }; static const char *const addrs2[] = { "::1", "::2", "::3", }; static const char *const addrs3[] = { "00:00:00:00:00:01", "00:00:00:00:00:02", "00:00:00:00:00:03", }; static const char *const addrs4[] = { NULL }; expr_const_sets_add(addr_sets, "set1", addrs1, 3, true); expr_const_sets_add(addr_sets, "set2", addrs2, 3, true); expr_const_sets_add(addr_sets, "set3", addrs3, 3, true); expr_const_sets_add(addr_sets, "set4", addrs4, 0, true); }
void ovn_init_symtab(struct shash *symtab) { shash_init(symtab); /* Reserve a pair of registers for the logical inport and outport. A full * 32-bit register each is bigger than we need, but the expression code * doesn't yet support string fields that occupy less than a full OXM. */ expr_symtab_add_string(symtab, "inport", MFF_LOG_INPORT, NULL); expr_symtab_add_string(symtab, "outport", MFF_LOG_OUTPORT, NULL); /* Logical registers: * 128-bit xxregs * 64-bit xregs * 32-bit regs * * The expression language doesn't handle overlapping fields properly * unless they're formally defined as subfields. It's a little awkward. */ for (int xxi = 0; xxi < MFF_N_LOG_REGS / 4; xxi++) { char *xxname = xasprintf("xxreg%d", xxi); expr_symtab_add_field(symtab, xxname, MFF_XXREG0 + xxi, NULL, false); free(xxname); } for (int xi = 0; xi < MFF_N_LOG_REGS / 2; xi++) { char *xname = xasprintf("xreg%d", xi); int xxi = xi / 2; if (xxi < MFF_N_LOG_REGS / 4) { add_subregister(xname, "xxreg", xxi, 64, 1 - xi % 2, symtab); } else { expr_symtab_add_field(symtab, xname, MFF_XREG0 + xi, NULL, false); } free(xname); } for (int i = 0; i < MFF_N_LOG_REGS; i++) { char *name = xasprintf("reg%d", i); int xxi = i / 4; int xi = i / 2; if (xxi < MFF_N_LOG_REGS / 4) { add_subregister(name, "xxreg", xxi, 32, 3 - i % 4, symtab); } else if (xi < MFF_N_LOG_REGS / 2) { add_subregister(name, "xreg", xi, 32, 1 - i % 2, symtab); } else { expr_symtab_add_field(symtab, name, MFF_REG0 + i, NULL, false); } free(name); } /* Flags used in logical to physical transformation. */ expr_symtab_add_field(symtab, "flags", MFF_LOG_FLAGS, NULL, false); char flags_str[16]; snprintf(flags_str, sizeof flags_str, "flags[%d]", MLF_ALLOW_LOOPBACK_BIT); expr_symtab_add_subfield(symtab, "flags.loopback", NULL, flags_str); snprintf(flags_str, sizeof flags_str, "flags[%d]", MLF_FORCE_SNAT_FOR_DNAT_BIT); expr_symtab_add_subfield(symtab, "flags.force_snat_for_dnat", NULL, flags_str); snprintf(flags_str, sizeof flags_str, "flags[%d]", MLF_FORCE_SNAT_FOR_LB_BIT); expr_symtab_add_subfield(symtab, "flags.force_snat_for_lb", NULL, flags_str); /* Connection tracking state. */ expr_symtab_add_field(symtab, "ct_mark", MFF_CT_MARK, NULL, false); expr_symtab_add_field(symtab, "ct_label", MFF_CT_LABEL, NULL, false); expr_symtab_add_subfield(symtab, "ct_label.blocked", NULL, "ct_label[0]"); expr_symtab_add_field(symtab, "ct_state", MFF_CT_STATE, NULL, false); struct ct_bit { const char *name; int bit; }; static const struct ct_bit bits[] = { {"trk", CS_TRACKED_BIT}, {"new", CS_NEW_BIT}, {"est", CS_ESTABLISHED_BIT}, {"rel", CS_RELATED_BIT}, {"rpl", CS_REPLY_DIR_BIT}, {"inv", CS_INVALID_BIT}, {"dnat", CS_DST_NAT_BIT}, {"snat", CS_SRC_NAT_BIT}, }; for (const struct ct_bit *b = bits; b < &bits[ARRAY_SIZE(bits)]; b++) { char *name = xasprintf("ct.%s", b->name); char *expansion = xasprintf("ct_state[%d]", b->bit); const char *prereqs = b->bit == CS_TRACKED_BIT ? NULL : "ct.trk"; expr_symtab_add_subfield(symtab, name, prereqs, expansion); free(expansion); free(name); } /* Data fields. */ expr_symtab_add_field(symtab, "eth.src", MFF_ETH_SRC, NULL, false); expr_symtab_add_field(symtab, "eth.dst", MFF_ETH_DST, NULL, false); expr_symtab_add_field(symtab, "eth.type", MFF_ETH_TYPE, NULL, true); expr_symtab_add_predicate(symtab, "eth.bcast", "eth.dst == ff:ff:ff:ff:ff:ff"); expr_symtab_add_subfield(symtab, "eth.mcast", NULL, "eth.dst[40]"); expr_symtab_add_field(symtab, "vlan.tci", MFF_VLAN_TCI, NULL, false); expr_symtab_add_predicate(symtab, "vlan.present", "vlan.tci[12]"); expr_symtab_add_subfield(symtab, "vlan.pcp", "vlan.present", "vlan.tci[13..15]"); expr_symtab_add_subfield(symtab, "vlan.vid", "vlan.present", "vlan.tci[0..11]"); expr_symtab_add_predicate(symtab, "ip4", "eth.type == 0x800"); expr_symtab_add_predicate(symtab, "ip6", "eth.type == 0x86dd"); expr_symtab_add_predicate(symtab, "ip", "ip4 || ip6"); expr_symtab_add_field(symtab, "ip.proto", MFF_IP_PROTO, "ip", true); expr_symtab_add_field(symtab, "ip.dscp", MFF_IP_DSCP_SHIFTED, "ip", false); expr_symtab_add_field(symtab, "ip.ecn", MFF_IP_ECN, "ip", false); expr_symtab_add_field(symtab, "ip.ttl", MFF_IP_TTL, "ip", false); expr_symtab_add_field(symtab, "ip4.src", MFF_IPV4_SRC, "ip4", false); expr_symtab_add_field(symtab, "ip4.dst", MFF_IPV4_DST, "ip4", false); expr_symtab_add_predicate(symtab, "ip4.mcast", "ip4.dst[28..31] == 0xe"); expr_symtab_add_predicate(symtab, "icmp4", "ip4 && ip.proto == 1"); expr_symtab_add_field(symtab, "icmp4.type", MFF_ICMPV4_TYPE, "icmp4", false); expr_symtab_add_field(symtab, "icmp4.code", MFF_ICMPV4_CODE, "icmp4", false); expr_symtab_add_field(symtab, "ip6.src", MFF_IPV6_SRC, "ip6", false); expr_symtab_add_field(symtab, "ip6.dst", MFF_IPV6_DST, "ip6", false); expr_symtab_add_field(symtab, "ip6.label", MFF_IPV6_LABEL, "ip6", false); expr_symtab_add_predicate(symtab, "icmp6", "ip6 && ip.proto == 58"); expr_symtab_add_field(symtab, "icmp6.type", MFF_ICMPV6_TYPE, "icmp6", true); expr_symtab_add_field(symtab, "icmp6.code", MFF_ICMPV6_CODE, "icmp6", true); expr_symtab_add_predicate(symtab, "icmp", "icmp4 || icmp6"); expr_symtab_add_field(symtab, "ip.frag", MFF_IP_FRAG, "ip", false); expr_symtab_add_predicate(symtab, "ip.is_frag", "ip.frag[0]"); expr_symtab_add_predicate(symtab, "ip.later_frag", "ip.frag[1]"); expr_symtab_add_predicate(symtab, "ip.first_frag", "ip.is_frag && !ip.later_frag"); expr_symtab_add_predicate(symtab, "arp", "eth.type == 0x806"); expr_symtab_add_field(symtab, "arp.op", MFF_ARP_OP, "arp", false); expr_symtab_add_field(symtab, "arp.spa", MFF_ARP_SPA, "arp", false); expr_symtab_add_field(symtab, "arp.sha", MFF_ARP_SHA, "arp", false); expr_symtab_add_field(symtab, "arp.tpa", MFF_ARP_TPA, "arp", false); expr_symtab_add_field(symtab, "arp.tha", MFF_ARP_THA, "arp", false); expr_symtab_add_predicate(symtab, "nd", "icmp6.type == {135, 136} && icmp6.code == 0 && ip.ttl == 255"); expr_symtab_add_predicate(symtab, "nd_ns", "icmp6.type == 135 && icmp6.code == 0 && ip.ttl == 255"); expr_symtab_add_predicate(symtab, "nd_na", "icmp6.type == 136 && icmp6.code == 0 && ip.ttl == 255"); expr_symtab_add_field(symtab, "nd.target", MFF_ND_TARGET, "nd", false); expr_symtab_add_field(symtab, "nd.sll", MFF_ND_SLL, "nd_ns", false); expr_symtab_add_field(symtab, "nd.tll", MFF_ND_TLL, "nd_na", false); expr_symtab_add_predicate(symtab, "tcp", "ip.proto == 6"); expr_symtab_add_field(symtab, "tcp.src", MFF_TCP_SRC, "tcp", false); expr_symtab_add_field(symtab, "tcp.dst", MFF_TCP_DST, "tcp", false); expr_symtab_add_field(symtab, "tcp.flags", MFF_TCP_FLAGS, "tcp", false); expr_symtab_add_predicate(symtab, "udp", "ip.proto == 17"); expr_symtab_add_field(symtab, "udp.src", MFF_UDP_SRC, "udp", false); expr_symtab_add_field(symtab, "udp.dst", MFF_UDP_DST, "udp", false); expr_symtab_add_predicate(symtab, "sctp", "ip.proto == 132"); expr_symtab_add_field(symtab, "sctp.src", MFF_SCTP_SRC, "sctp", false); expr_symtab_add_field(symtab, "sctp.dst", MFF_SCTP_DST, "sctp", false); }
// create a new locl_subsystem object static struct locl_subsystem * add_subsystem(const struct ovsrec_subsystem *ovsrec_subsys) { struct locl_subsystem *result; int rc; int idx; struct ovsdb_idl_txn *txn; struct ovsrec_temp_sensor **sensor_array; int sensor_idx; int sensor_count; const char *dir; const YamlThermalInfo *info; // create and initialize basic subsystem information VLOG_DBG("Adding new subsystem %s", ovsrec_subsys->name); result = (struct locl_subsystem *)malloc(sizeof(struct locl_subsystem)); memset(result, 0, sizeof(struct locl_subsystem)); (void)shash_add(&subsystem_data, ovsrec_subsys->name, (void *)result); result->name = strdup(ovsrec_subsys->name); result->marked = false; result->marked = true; result->parent_subsystem = NULL; // OPS_TODO: find parent subsystem shash_init(&result->subsystem_sensors); // use a default if the hw_desc_dir has not been populated dir = ovsrec_subsys->hw_desc_dir; if (dir == NULL || strlen(dir) == 0) { VLOG_ERR("No h/w description directory for subsystem %s", ovsrec_subsys->name); return(NULL); } // since this is a new subsystem, load all of the hardware description // information about devices and sensors (just for this subsystem). // parse sensors and device data for subsystem rc = yaml_add_subsystem(yaml_handle, ovsrec_subsys->name, dir); if (rc != 0) { VLOG_ERR("Error reading h/w description files for subsystem %s", ovsrec_subsys->name); return(NULL); } // need devices data rc = yaml_parse_devices(yaml_handle, ovsrec_subsys->name); if (rc != 0) { VLOG_ERR("Unable to parse subsystem %s devices file (in %s)", ovsrec_subsys->name, dir); return(NULL); } // need thermal (sensor) data rc = yaml_parse_thermal(yaml_handle, ovsrec_subsys->name); if (rc != 0) { VLOG_ERR("Unable to parse subsystem %s thermal file (in %s)", ovsrec_subsys->name, dir); return(NULL); } // get the thermal info, need it for shutdown flag info = yaml_get_thermal_info(yaml_handle, ovsrec_subsys->name); result->emergency_shutdown = info->auto_shutdown; // OPS_TODO: the thermal info has a polling period, but when we // OPS_TODO: have multiple subsystems, that could be tricky to // OPS_TODO: implement if there are different polling periods. // OPS_TODO: For now, hardware the polling period to 5 seconds. // prepare to add sensors to db sensor_idx = 0; sensor_count = yaml_get_sensor_count(yaml_handle, ovsrec_subsys->name); if (sensor_count <= 0) { return(NULL); } result->valid = true; // subsystem db object has reference array for sensors sensor_array = (struct ovsrec_temp_sensor **)malloc(sensor_count * sizeof(struct ovsrec_temp_sensor *)); memset(sensor_array, 0, sensor_count * sizeof(struct ovsrec_temp_sensor *)); txn = ovsdb_idl_txn_create(idl); VLOG_DBG("There are %d sensors in subsystem %s", sensor_count, ovsrec_subsys->name); for (idx = 0; idx < sensor_count; idx++) { const YamlSensor *sensor = yaml_get_sensor(yaml_handle, ovsrec_subsys->name, idx); struct ovsrec_temp_sensor *ovs_sensor; char *sensor_name = NULL; struct locl_sensor *new_sensor; VLOG_DBG("Adding sensor %d (%s) in subsystem %s", sensor->number, sensor->location, ovsrec_subsys->name); // create a name for the sensor from the subsystem name and the // sensor number asprintf(&sensor_name, "%s-%d", ovsrec_subsys->name, sensor->number); // allocate and initialize basic sensor information new_sensor = (struct locl_sensor *)malloc(sizeof(struct locl_sensor)); new_sensor->name = sensor_name; new_sensor->subsystem = result; new_sensor->yaml_sensor = sensor; new_sensor->min = 1000000; new_sensor->max = -1000000; new_sensor->temp = 0; new_sensor->status = SENSOR_STATUS_NORMAL; new_sensor->fan_speed = SENSOR_FAN_NORMAL; new_sensor->test_temp = -1; // no test temperature override set // try to populate sensor information with real data tempd_read_sensor(new_sensor); // add sensor to subsystem sensor dictionary shash_add(&result->subsystem_sensors, sensor_name, (void *)new_sensor); // add sensor to global sensor dictionary shash_add(&sensor_data, sensor_name, (void *)new_sensor); // look for existing Temp_sensor rows ovs_sensor = lookup_sensor(sensor_name); if (ovs_sensor == NULL) { // existing sensor doesn't exist in db, create it ovs_sensor = ovsrec_temp_sensor_insert(txn); } // set initial data ovsrec_temp_sensor_set_name(ovs_sensor, sensor_name); ovsrec_temp_sensor_set_status(ovs_sensor, sensor_status_to_string(new_sensor->status)); ovsrec_temp_sensor_set_temperature(ovs_sensor, new_sensor->temp); ovsrec_temp_sensor_set_min(ovs_sensor, new_sensor->min); ovsrec_temp_sensor_set_max(ovs_sensor, new_sensor->max); ovsrec_temp_sensor_set_fan_state(ovs_sensor, sensor_speed_to_string(new_sensor->fan_speed)); ovsrec_temp_sensor_set_location(ovs_sensor, sensor->location); // add sensor to subsystem reference list sensor_array[sensor_idx++] = ovs_sensor; } ovsrec_subsystem_set_temp_sensors(ovsrec_subsys, sensor_array, sensor_count); // execute transaction ovsdb_idl_txn_commit_block(txn); ovsdb_idl_txn_destroy(txn); free(sensor_array); return(result); }
// initialize the subsystem and global sensor dictionaries static void init_subsystems(void) { shash_init(&subsystem_data); shash_init(&sensor_data); }
int main(int argc, char *argv[]) { struct ovsdb_idl *idl; struct ctl_command *commands; struct shash local_options; unsigned int seqno; size_t n_commands; char *args; set_program_name(argv[0]); fatal_ignore_sigpipe(); vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN); vlog_set_levels_from_string_assert("reconnect:warn"); sbrec_init(); sbctl_cmd_init(); /* Log our arguments. This is often valuable for debugging systems. */ args = process_escape_args(argv); VLOG(ctl_might_write_to_db(argv) ? VLL_INFO : VLL_DBG, "Called as %s", args); /* Parse command line. */ shash_init(&local_options); parse_options(argc, argv, &local_options); commands = ctl_parse_commands(argc - optind, argv + optind, &local_options, &n_commands); if (timeout) { time_alarm(timeout); } /* Initialize IDL. */ idl = the_idl = ovsdb_idl_create(db, &sbrec_idl_class, false, false); run_prerequisites(commands, n_commands, idl); /* Execute the commands. * * 'seqno' is the database sequence number for which we last tried to * execute our transaction. There's no point in trying to commit more than * once for any given sequence number, because if the transaction fails * it's because the database changed and we need to obtain an up-to-date * view of the database before we try the transaction again. */ seqno = ovsdb_idl_get_seqno(idl); for (;;) { ovsdb_idl_run(idl); if (!ovsdb_idl_is_alive(idl)) { int retval = ovsdb_idl_get_last_error(idl); ctl_fatal("%s: database connection failed (%s)", db, ovs_retval_to_string(retval)); } if (seqno != ovsdb_idl_get_seqno(idl)) { seqno = ovsdb_idl_get_seqno(idl); if (do_sbctl(args, commands, n_commands, idl)) { free(args); exit(EXIT_SUCCESS); } } if (seqno == ovsdb_idl_get_seqno(idl)) { ovsdb_idl_wait(idl); poll_block(); } } }
static void symtab_init(void) { shash_init(&symtab); /* Reserve a pair of registers for the logical inport and outport. A full * 32-bit register each is bigger than we need, but the expression code * doesn't yet support string fields that occupy less than a full OXM. */ expr_symtab_add_string(&symtab, "inport", MFF_LOG_INPORT, NULL); expr_symtab_add_string(&symtab, "outport", MFF_LOG_OUTPORT, NULL); /* Logical registers. */ #define MFF_LOG_REG(ID) add_logical_register(&symtab, ID); MFF_LOG_REGS; #undef MFF_LOG_REG /* Connection tracking state. */ expr_symtab_add_field(&symtab, "ct_state", MFF_CT_STATE, NULL, false); char ct_state_str[16]; snprintf(ct_state_str, sizeof ct_state_str, "ct_state[%d]", CS_TRACKED_BIT); expr_symtab_add_predicate(&symtab, "ct.trk", ct_state_str); snprintf(ct_state_str, sizeof ct_state_str, "ct_state[%d]", CS_NEW_BIT); expr_symtab_add_subfield(&symtab, "ct.new", "ct.trk", ct_state_str); snprintf(ct_state_str, sizeof ct_state_str, "ct_state[%d]", CS_ESTABLISHED_BIT); expr_symtab_add_subfield(&symtab, "ct.est", "ct.trk", ct_state_str); snprintf(ct_state_str, sizeof ct_state_str, "ct_state[%d]", CS_RELATED_BIT); expr_symtab_add_subfield(&symtab, "ct.rel", "ct.trk", ct_state_str); snprintf(ct_state_str, sizeof ct_state_str, "ct_state[%d]", CS_REPLY_DIR_BIT); expr_symtab_add_subfield(&symtab, "ct.rpl", "ct.trk", ct_state_str); snprintf(ct_state_str, sizeof ct_state_str, "ct_state[%d]", CS_INVALID_BIT); expr_symtab_add_subfield(&symtab, "ct.inv", "ct.trk", ct_state_str); /* Data fields. */ expr_symtab_add_field(&symtab, "eth.src", MFF_ETH_SRC, NULL, false); expr_symtab_add_field(&symtab, "eth.dst", MFF_ETH_DST, NULL, false); expr_symtab_add_field(&symtab, "eth.type", MFF_ETH_TYPE, NULL, true); expr_symtab_add_predicate(&symtab, "eth.bcast", "eth.dst == ff:ff:ff:ff:ff:ff"); expr_symtab_add_subfield(&symtab, "eth.mcast", NULL, "eth.dst[40]"); expr_symtab_add_field(&symtab, "vlan.tci", MFF_VLAN_TCI, NULL, false); expr_symtab_add_predicate(&symtab, "vlan.present", "vlan.tci[12]"); expr_symtab_add_subfield(&symtab, "vlan.pcp", "vlan.present", "vlan.tci[13..15]"); expr_symtab_add_subfield(&symtab, "vlan.vid", "vlan.present", "vlan.tci[0..11]"); expr_symtab_add_predicate(&symtab, "ip4", "eth.type == 0x800"); expr_symtab_add_predicate(&symtab, "ip6", "eth.type == 0x86dd"); expr_symtab_add_predicate(&symtab, "ip", "ip4 || ip6"); expr_symtab_add_field(&symtab, "ip.proto", MFF_IP_PROTO, "ip", true); expr_symtab_add_field(&symtab, "ip.dscp", MFF_IP_DSCP, "ip", false); expr_symtab_add_field(&symtab, "ip.ecn", MFF_IP_ECN, "ip", false); expr_symtab_add_field(&symtab, "ip.ttl", MFF_IP_TTL, "ip", false); expr_symtab_add_field(&symtab, "ip4.src", MFF_IPV4_SRC, "ip4", false); expr_symtab_add_field(&symtab, "ip4.dst", MFF_IPV4_DST, "ip4", false); expr_symtab_add_predicate(&symtab, "ip4.mcast", "ip4.dst[28..31] == 0xe"); expr_symtab_add_predicate(&symtab, "icmp4", "ip4 && ip.proto == 1"); expr_symtab_add_field(&symtab, "icmp4.type", MFF_ICMPV4_TYPE, "icmp4", false); expr_symtab_add_field(&symtab, "icmp4.code", MFF_ICMPV4_CODE, "icmp4", false); expr_symtab_add_field(&symtab, "ip6.src", MFF_IPV6_SRC, "ip6", false); expr_symtab_add_field(&symtab, "ip6.dst", MFF_IPV6_DST, "ip6", false); expr_symtab_add_field(&symtab, "ip6.label", MFF_IPV6_LABEL, "ip6", false); expr_symtab_add_predicate(&symtab, "icmp6", "ip6 && ip.proto == 58"); expr_symtab_add_field(&symtab, "icmp6.type", MFF_ICMPV6_TYPE, "icmp6", true); expr_symtab_add_field(&symtab, "icmp6.code", MFF_ICMPV6_CODE, "icmp6", true); expr_symtab_add_predicate(&symtab, "icmp", "icmp4 || icmp6"); expr_symtab_add_field(&symtab, "ip.frag", MFF_IP_FRAG, "ip", false); expr_symtab_add_predicate(&symtab, "ip.is_frag", "ip.frag[0]"); expr_symtab_add_predicate(&symtab, "ip.later_frag", "ip.frag[1]"); expr_symtab_add_predicate(&symtab, "ip.first_frag", "ip.is_frag && !ip.later_frag"); expr_symtab_add_predicate(&symtab, "arp", "eth.type == 0x806"); expr_symtab_add_field(&symtab, "arp.op", MFF_ARP_OP, "arp", false); expr_symtab_add_field(&symtab, "arp.spa", MFF_ARP_SPA, "arp", false); expr_symtab_add_field(&symtab, "arp.sha", MFF_ARP_SHA, "arp", false); expr_symtab_add_field(&symtab, "arp.tpa", MFF_ARP_TPA, "arp", false); expr_symtab_add_field(&symtab, "arp.tha", MFF_ARP_THA, "arp", false); expr_symtab_add_predicate(&symtab, "nd", "icmp6.type == {135, 136} && icmp6.code == 0"); expr_symtab_add_field(&symtab, "nd.target", MFF_ND_TARGET, "nd", false); expr_symtab_add_field(&symtab, "nd.sll", MFF_ND_SLL, "nd && icmp6.type == 135", false); expr_symtab_add_field(&symtab, "nd.tll", MFF_ND_TLL, "nd && icmp6.type == 136", false); expr_symtab_add_predicate(&symtab, "tcp", "ip.proto == 6"); expr_symtab_add_field(&symtab, "tcp.src", MFF_TCP_SRC, "tcp", false); expr_symtab_add_field(&symtab, "tcp.dst", MFF_TCP_DST, "tcp", false); expr_symtab_add_field(&symtab, "tcp.flags", MFF_TCP_FLAGS, "tcp", false); expr_symtab_add_predicate(&symtab, "udp", "ip.proto == 17"); expr_symtab_add_field(&symtab, "udp.src", MFF_UDP_SRC, "udp", false); expr_symtab_add_field(&symtab, "udp.dst", MFF_UDP_DST, "udp", false); expr_symtab_add_predicate(&symtab, "sctp", "ip.proto == 132"); expr_symtab_add_field(&symtab, "sctp.src", MFF_SCTP_SRC, "sctp", false); expr_symtab_add_field(&symtab, "sctp.dst", MFF_SCTP_DST, "sctp", false); }