void parse_ofp_flow_mod_file(const char *file_name, uint16_t command, struct ofputil_flow_mod **fms, size_t *n_fms) { size_t allocated_fms; FILE *stream; struct ds s; stream = !strcmp(file_name, "-") ? stdin : fopen(file_name, "r"); if (stream == NULL) { ovs_fatal(errno, "%s: open", file_name); } allocated_fms = *n_fms; ds_init(&s); while (!ds_get_preprocessed_line(&s, stream)) { if (*n_fms >= allocated_fms) { *fms = x2nrealloc(*fms, &allocated_fms, sizeof **fms); } parse_ofp_flow_mod_str(&(*fms)[*n_fms], ds_cstr(&s), command, false); *n_fms += 1; } ds_destroy(&s); if (stream != stdin) { fclose(stream); } }
/* Similar to parse_ofp_flow_mod_str(), except that the string is read from * 'stream' and the command is always OFPFC_ADD. Returns false if end-of-file * is reached before reading a flow, otherwise true. */ bool parse_ofp_flow_mod_file(struct list *packets, enum nx_flow_format *cur, bool *flow_mod_table_id, FILE *stream, uint16_t command) { struct ds s; bool ok; ds_init(&s); ok = ds_get_preprocessed_line(&s, stream) == 0; if (ok) { parse_ofp_flow_mod_str(packets, cur, flow_mod_table_id, ds_cstr(&s), command, true); } ds_destroy(&s); return ok; }
/* Opens file 'file_name' and reads each line as a flow_mod or a group_mod, * depending on the first keyword on each line. Stores each flow and group * mods in '*bms', an array allocated on the caller's behalf, and the number of * messages in '*n_bms'. * * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT parse_ofp_bundle_file(const char *file_name, const struct ofputil_port_map *port_map, const struct ofputil_table_map *table_map, struct ofputil_bundle_msg **bms, size_t *n_bms, enum ofputil_protocol *usable_protocols) { size_t allocated_bms; char *error = NULL; int line_number; FILE *stream; struct ds ds; *usable_protocols = OFPUTIL_P_ANY; *bms = NULL; *n_bms = 0; stream = !strcmp(file_name, "-") ? stdin : fopen(file_name, "r"); if (stream == NULL) { return xasprintf("%s: open failed (%s)", file_name, ovs_strerror(errno)); } allocated_bms = *n_bms; ds_init(&ds); line_number = 0; while (!ds_get_preprocessed_line(&ds, stream, &line_number)) { enum ofputil_protocol usable; char *s = ds_cstr(&ds); size_t len; if (*n_bms >= allocated_bms) { struct ofputil_bundle_msg *new_bms; new_bms = x2nrealloc(*bms, &allocated_bms, sizeof **bms); for (size_t i = 0; i < *n_bms; i++) { if (new_bms[i].type == OFPTYPE_GROUP_MOD) { ovs_list_moved(&new_bms[i].gm.buckets, &(*bms)[i].gm.buckets); } } *bms = new_bms; } s += strspn(s, " \t\r\n"); /* Skip white space. */ len = strcspn(s, ", \t\r\n"); /* Get length of the first token. */ if (!strncmp(s, "flow", len)) { s += len; error = parse_ofp_flow_mod_str(&(*bms)[*n_bms].fm, s, port_map, table_map, -2, &usable); if (error) { break; } (*bms)[*n_bms].type = OFPTYPE_FLOW_MOD; } else if (!strncmp(s, "group", len)) { s += len; error = parse_ofp_group_mod_str(&(*bms)[*n_bms].gm, -2, s, port_map, table_map, &usable); if (error) { break; } (*bms)[*n_bms].type = OFPTYPE_GROUP_MOD; } else if (!strncmp(s, "packet-out", len)) { s += len; error = parse_ofp_packet_out_str(&(*bms)[*n_bms].po, s, port_map, table_map, &usable); if (error) { break; } (*bms)[*n_bms].type = OFPTYPE_PACKET_OUT; } else { error = xasprintf("Unsupported bundle message type: %.*s", (int)len, s); break; } *usable_protocols &= usable; /* Each line can narrow the set. */ *n_bms += 1; } ds_destroy(&ds); if (stream != stdin) { fclose(stream); } if (error) { char *err_msg = xasprintf("%s:%d: %s", file_name, line_number, error); free(error); ofputil_free_bundle_msgs(*bms, *n_bms); *bms = NULL; *n_bms = 0; return err_msg; } return NULL; }