一、首包精确流表生成
首包到达OVS交换机时,尚未建立基于目的mac的流表规则,需要upcall到用户态进行学习,此时生成的规则是把报文flood到其他端口。
1、upcall_xlate函数
upcall->dump_seq = seq_read(udpif->dump_seq);
upcall->reval_seq = seq_read(udpif->reval_seq);
xlate_actions(&xin, &upcall->xout);
upcall->xout_initialized = true;
2、xlate_actions函数
<pre name="code" class="cpp"> /* The bridge is now known so obtain its table version. */
ctx.tables_version = ofproto_dpif_get_tables_version(ctx.xbridge->ofproto);
if (!xin->ofpacts && !ctx.rule) {
ctx.rule = rule_dpif_lookup_from_table( //检索流表
ctx.xbridge->ofproto, ctx.tables_version, flow, xin->wc,
ctx.xin->resubmit_stats, &ctx.table_id,
flow->in_port.ofp_port, true, true);
if (ctx.xin->resubmit_stats) {
rule_dpif_credit_stats(ctx.rule, ctx.xin->resubmit_stats);
}
if (ctx.xin->xcache) {
struct xc_entry *entry;
entry = xlate_cache_add_entry(ctx.xin->xcache, XC_RULE);
entry->u.rule = ctx.rule;
rule_dpif_ref(ctx.rule);
}
if (OVS_UNLIKELY(ctx.xin->resubmit_hook)) {
ctx.xin->resubmit_hook(ctx.xin, ctx.rule, 0);
}
}
xout->fail_open = ctx.rule && rule_dpif_is_fail_open(ctx.rule);
/* Get the proximate input port of the packet. (If xin->recirc,
* flow->in_port is the ultimate input port of the packet.) */
struct xport *in_port = get_ofp_port(xbridge,
ctx.base_flow.in_port.ofp_port);
/* Tunnel stats only for non-recirculated packets. */
if (!xin->recirc && in_port && in_port->is_tunnel) {
if (ctx.xin->resubmit_stats) {
netdev_vport_inc_rx(in_port->netdev, ctx.xin->resubmit_stats);
if (in_port->bfd) {
bfd_account_rx(in_port->bfd, ctx.xin->resubmit_stats);
}
}
if (ctx.xin->xcache) {
struct xc_entry *entry;
entry = xlate_cache_add_entry(ctx.xin->xcache, XC_NETDEV);
entry->u.dev.rx = netdev_ref(in_port->netdev);
entry->u.dev.bfd = bfd_ref(in_port->bfd);
}
}
if (!xin->recirc && process_special(&ctx, in_port)) {
/* process_special() did all the processing for this packet.
*
* We do not perform special processing on recirculated packets, as
* recirculated packets are not really received by the bridge.*/
} else if (in_port && in_port->xbundle
&& xbundle_mirror_out(xbridge, in_port->xbundle)) {
if (ctx.xin->packet != NULL) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
VLOG_WARN_RL(&rl, "bridge %s: dropping packet received on port "
"%s, which is reserved exclusively for mirroring",
ctx.xbridge->name, in_port->xbundle->name);
}
} else {
/* Sampling is done only for packets really received by th