zoukankan      html  css  js  c++  java
  • openvswitch datapath 内核态流表创建过程(ovs_flow_cmd_new)

    datapath流表更新的入口函数都定义在dp_flow_genl_ops中,流表创建的入口函数是ovs_flow_cmd_new函数,通过该函数,我们可以一窥流表相关信息的建立。

    1、ovs_flow_cmd_new函数

      1 static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
      2 {
      3     struct net *net = sock_net(skb->sk);
      4     struct nlattr **a = info->attrs;
      5     struct ovs_header *ovs_header = info->userhdr;
      6     struct sw_flow *flow = NULL, *new_flow;
      7     struct sw_flow_mask mask;
      8     struct sk_buff *reply;
      9     struct datapath *dp;
     10     struct sw_flow_actions *acts;
     11     struct sw_flow_match match;
     12     u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
     13     int error;
     14     bool log = !a[OVS_FLOW_ATTR_PROBE];
     15 
     16     /* Must have key and actions. */
     17     error = -EINVAL;
     18     if (!a[OVS_FLOW_ATTR_KEY]) {
     19         OVS_NLERR(log, "Flow key attr not present in new flow.");
     20         goto error;
     21     }
     22     if (!a[OVS_FLOW_ATTR_ACTIONS]) {
     23         OVS_NLERR(log, "Flow actions attr not present in new flow.");
     24         goto error;
     25     }
     26 
     27     /* Most of the time we need to allocate a new flow, do it before
     28      * locking.
     29      */
     30     new_flow = ovs_flow_alloc();
     31     if (IS_ERR(new_flow)) {
     32         error = PTR_ERR(new_flow);
     33         goto error;
     34     }
     35 
     36     /* Extract key. */
     37     ovs_match_init(&match, &new_flow->key, false, &mask);
     38     error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
     39                   a[OVS_FLOW_ATTR_MASK], log);
     40     if (error)
     41         goto err_kfree_flow;
     42 
     43     /* Extract flow identifier. */
     44     error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID],
     45                        &new_flow->key, log);
     46     if (error)
     47         goto err_kfree_flow;
     48 
     49     /* unmasked key is needed to match when ufid is not used. */
     50     if (ovs_identifier_is_key(&new_flow->id))
     51         match.key = new_flow->id.unmasked_key;
     52 
     53     ovs_flow_mask_key(&new_flow->key, &new_flow->key, true, &mask);
     54 
     55     /* Validate actions. */
     56     error = ovs_nla_copy_actions(net, a[OVS_FLOW_ATTR_ACTIONS],
     57                      &new_flow->key, &acts, log);
     58     if (error) {
     59         OVS_NLERR(log, "Flow actions may not be safe on all matching packets.");
     60         goto err_kfree_flow;
     61     }
     62 
     63     reply = ovs_flow_cmd_alloc_info(acts, &new_flow->id, info, false,
     64                     ufid_flags);
     65     if (IS_ERR(reply)) {
     66         error = PTR_ERR(reply);
     67         goto err_kfree_acts;
     68     }
     69 
     70     ovs_lock();
     71     dp = get_dp(net, ovs_header->dp_ifindex);
     72     if (unlikely(!dp)) {
     73         error = -ENODEV;
     74         goto err_unlock_ovs;
     75     }
     76 
     77     /* Check if this is a duplicate flow */
     78     if (ovs_identifier_is_ufid(&new_flow->id))
     79         flow = ovs_flow_tbl_lookup_ufid(&dp->table, &new_flow->id);
     80     if (!flow)
     81         flow = ovs_flow_tbl_lookup(&dp->table, &new_flow->key);
     82     if (likely(!flow)) {
     83         rcu_assign_pointer(new_flow->sf_acts, acts);
     84 
     85         /* Put flow in bucket. */
     86         error = ovs_flow_tbl_insert(&dp->table, new_flow, &mask);
     87         if (unlikely(error)) {
     88             acts = NULL;
     89             goto err_unlock_ovs;
     90         }
     91 
     92         if (unlikely(reply)) {
     93             error = ovs_flow_cmd_fill_info(new_flow,
     94                                ovs_header->dp_ifindex,
     95                                reply, info->snd_portid,
     96                                info->snd_seq, 0,
     97                                OVS_FLOW_CMD_NEW,
     98                                ufid_flags);
     99             BUG_ON(error < 0);
    100         }
    101         ovs_unlock();
    102     } else {
    103         struct sw_flow_actions *old_acts;
    104 
    105         /* Bail out if we're not allowed to modify an existing flow.
    106          * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL
    107          * because Generic Netlink treats the latter as a dump
    108          * request.  We also accept NLM_F_EXCL in case that bug ever
    109          * gets fixed.
    110          */
    111         if (unlikely(info->nlhdr->nlmsg_flags & (NLM_F_CREATE
    112                              | NLM_F_EXCL))) {
    113             error = -EEXIST;
    114             goto err_unlock_ovs;
    115         }
    116         /* The flow identifier has to be the same for flow updates.
    117          * Look for any overlapping flow.
    118          */
    119         if (unlikely(!ovs_flow_cmp(flow, &match))) {
    120             if (ovs_identifier_is_key(&flow->id))
    121                 flow = ovs_flow_tbl_lookup_exact(&dp->table,
    122                                  &match);
    123             else /* UFID matches but key is different */
    124                 flow = NULL;
    125             if (!flow) {
    126                 error = -ENOENT;
    127                 goto err_unlock_ovs;
    128             }
    129         }
    130         /* Update actions. */
    131         old_acts = ovsl_dereference(flow->sf_acts);
    132         rcu_assign_pointer(flow->sf_acts, acts);
    133 
    134         if (unlikely(reply)) {
    135             error = ovs_flow_cmd_fill_info(flow,
    136                                ovs_header->dp_ifindex,
    137                                reply, info->snd_portid,
    138                                info->snd_seq, 0,
    139                                OVS_FLOW_CMD_NEW,
    140                                ufid_flags);
    141             BUG_ON(error < 0);
    142         }
    143         ovs_unlock();
    144 
    145         ovs_nla_free_flow_actions_rcu(old_acts);
    146         ovs_flow_free(new_flow, false);
    147     }
    148 
    149     if (reply)
    150         ovs_notify(&dp_flow_genl_family, &ovs_dp_flow_multicast_group, reply, info);
    151     return 0;
    152 
    153 err_unlock_ovs:
    154     ovs_unlock();
    155     kfree_skb(reply);
    156 err_kfree_acts:
    157     ovs_nla_free_flow_actions(acts);
    158 err_kfree_flow:
    159     ovs_flow_free(new_flow, false);
    160 error:
    161     return error;
    162 }

    2、ovs_flow_tbl_insert函数

     1 /* Must be called with OVS mutex held. */
     2 int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
     3             const struct sw_flow_mask *mask)
     4 {
     5     int err;
     6 
     7     err = flow_mask_insert(table, flow, mask);
     8     if (err)
     9         return err;
    10     flow_key_insert(table, flow);
    11     if (ovs_identifier_is_ufid(&flow->id))
    12         flow_ufid_insert(table, flow);
    13 
    14     return 0;
    15 }

    3、flow_mask_insert函数

     1 /* Add 'mask' into the mask list, if it is not already there. */
     2 static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow,
     3                 const struct sw_flow_mask *new)
     4 {
     5     struct sw_flow_mask *mask;
     6 
     7     mask = flow_mask_find(tbl, new);
     8     if (!mask) {
     9         struct mask_array *ma;
    10         int i;
    11 
    12         /* Allocate a new mask if none exsits. */
    13         mask = mask_alloc();
    14         if (!mask)
    15             return -ENOMEM;
    16 
    17         mask->key = new->key;
    18         mask->range = new->range;
    19 
    20         /* Add mask to mask-list. */
    21         ma = ovsl_dereference(tbl->mask_array);
    22         if (ma->count >= ma->max) {
    23             int err;
    24 
    25             err = tbl_mask_array_realloc(tbl, ma->max +
    26                               MASK_ARRAY_SIZE_MIN);
    27             if (err) {
    28                 kfree(mask);
    29                 return err;
    30             }
    31             ma = ovsl_dereference(tbl->mask_array);
    32         }
    33 
    34         for (i = 0; i < ma->max; i++) {
    35             struct sw_flow_mask *t;
    36 
    37             t = ovsl_dereference(ma->masks[i]);
    38             if (!t) {
    39                 rcu_assign_pointer(ma->masks[i], mask);
    40                 ma->count++;
    41                 break;
    42             }
    43         }
    44 
    45     } else {
    46         BUG_ON(!mask->ref_count);
    47         mask->ref_count++;
    48     }
    49 
    50     flow->mask = mask;
    51     return 0;
    52 }

    4、flow_key_insert函数

     1 /* Must be called with OVS mutex held. */
     2 static void flow_key_insert(struct flow_table *table, struct sw_flow *flow)
     3 {
     4     struct table_instance *new_ti = NULL;
     5     struct table_instance *ti;
     6 
     7     flow->flow_table.hash = flow_hash(&flow->key, &flow->mask->range);
     8     ti = ovsl_dereference(table->ti);
     9     table_instance_insert(ti, flow);
    10     table->count++;
    11 
    12     /* Expand table, if necessary, to make room. */
    13     if (table->count > ti->n_buckets)
    14         new_ti = table_instance_expand(ti, false);
    15     else if (time_after(jiffies, table->last_rehash + REHASH_INTERVAL))
    16         new_ti = table_instance_rehash(ti, ti->n_buckets, false);
    17 
    18     if (new_ti) {
    19         rcu_assign_pointer(table->ti, new_ti);
    20         call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
    21         table->last_rehash = jiffies;
    22     }
    23 }

    5、table_instance_insert函数

    1 static void table_instance_insert(struct table_instance *ti,
    2                   struct sw_flow *flow)
    3 {
    4     struct hlist_head *head;
    5 
    6     head = find_bucket(ti, flow->flow_table.hash);
    7     hlist_add_head_rcu(&flow->flow_table.node[ti->node_ver], head);
    8 }

     6、ovs_nla_copy_actions函数

     1 /* 'key' must be the masked key. */
     2 int ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
     3              const struct sw_flow_key *key,
     4              struct sw_flow_actions **sfa, bool log)
     5 {
     6     int err;
     7 
     8     *sfa = nla_alloc_flow_actions(min(nla_len(attr), MAX_ACTIONS_BUFSIZE));
     9     if (IS_ERR(*sfa))
    10         return PTR_ERR(*sfa);
    11 
    12     (*sfa)->orig_len = nla_len(attr);
    13     err = __ovs_nla_copy_actions(net, attr, key, sfa, key->eth.type,
    14                      key->eth.vlan.tci, log);
    15     if (err)
    16         ovs_nla_free_flow_actions(*sfa);
    17 
    18     return err;
    19 }

    7、__ovs_nla_copy_actions函数

      1 static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
      2                   const struct sw_flow_key *key,
      3                   struct sw_flow_actions **sfa,
      4                   __be16 eth_type, __be16 vlan_tci, bool log)
      5 {
      6     u8 mac_proto = ovs_key_mac_proto(key);
      7     const struct nlattr *a;
      8     int rem, err;
      9 
     10     nla_for_each_nested(a, attr, rem) {
     11         /* Expected argument lengths, (u32)-1 for variable length. */
     12         static const u32 action_lens[OVS_ACTION_ATTR_MAX + 1] = {
     13             [OVS_ACTION_ATTR_OUTPUT] = sizeof(u32),
     14             [OVS_ACTION_ATTR_RECIRC] = sizeof(u32),
     15             [OVS_ACTION_ATTR_USERSPACE] = (u32)-1,
     16             [OVS_ACTION_ATTR_PUSH_MPLS] = sizeof(struct ovs_action_push_mpls),
     17             [OVS_ACTION_ATTR_POP_MPLS] = sizeof(__be16),
     18             [OVS_ACTION_ATTR_PUSH_VLAN] = sizeof(struct ovs_action_push_vlan),
     19             [OVS_ACTION_ATTR_POP_VLAN] = 0,
     20             [OVS_ACTION_ATTR_SET] = (u32)-1,
     21             [OVS_ACTION_ATTR_SET_MASKED] = (u32)-1,
     22             [OVS_ACTION_ATTR_SAMPLE] = (u32)-1,
     23             [OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash),
     24             [OVS_ACTION_ATTR_CT] = (u32)-1,
     25             [OVS_ACTION_ATTR_CT_CLEAR] = 0,
     26             [OVS_ACTION_ATTR_TRUNC] = sizeof(struct ovs_action_trunc),
     27             [OVS_ACTION_ATTR_PUSH_ETH] = sizeof(struct ovs_action_push_eth),
     28             [OVS_ACTION_ATTR_POP_ETH] = 0,
     29             [OVS_ACTION_ATTR_PUSH_NSH] = (u32)-1,
     30             [OVS_ACTION_ATTR_POP_NSH] = 0,
     31         };
     32         const struct ovs_action_push_vlan *vlan;
     33         int type = nla_type(a);
     34         bool skip_copy;
     35 
     36         if (type > OVS_ACTION_ATTR_MAX ||
     37             (action_lens[type] != nla_len(a) &&
     38              action_lens[type] != (u32)-1))
     39             return -EINVAL;
     40 
     41         skip_copy = false;
     42         switch (type) {
     43         case OVS_ACTION_ATTR_UNSPEC:
     44             return -EINVAL;
     45 
     46         case OVS_ACTION_ATTR_USERSPACE:
     47             err = validate_userspace(a);
     48             if (err)
     49                 return err;
     50             break;
     51 
     52         case OVS_ACTION_ATTR_OUTPUT:
     53             if (nla_get_u32(a) >= DP_MAX_PORTS)
     54                 return -EINVAL;
     55             break;
     56 
     57         case OVS_ACTION_ATTR_TRUNC: {
     58             const struct ovs_action_trunc *trunc = nla_data(a);
     59 
     60             if (trunc->max_len < ETH_HLEN)
     61                 return -EINVAL;
     62             break;
     63         }
     64 
     65         case OVS_ACTION_ATTR_HASH: {
     66             const struct ovs_action_hash *act_hash = nla_data(a);
     67 
     68             switch (act_hash->hash_alg) {
     69             case OVS_HASH_ALG_L4:
     70                 break;
     71             default:
     72                 return  -EINVAL;
     73             }
     74 
     75             break;
     76         }
     77 
     78         case OVS_ACTION_ATTR_POP_VLAN:
     79             if (mac_proto != MAC_PROTO_ETHERNET)
     80                 return -EINVAL;
     81             vlan_tci = htons(0);
     82             break;
     83 
     84         case OVS_ACTION_ATTR_PUSH_VLAN:
     85             if (mac_proto != MAC_PROTO_ETHERNET)
     86                 return -EINVAL;
     87             vlan = nla_data(a);
     88             if (!eth_type_vlan(vlan->vlan_tpid))
     89                 return -EINVAL;
     90             if (!(vlan->vlan_tci & htons(VLAN_TAG_PRESENT)))
     91                 return -EINVAL;
     92             vlan_tci = vlan->vlan_tci;
     93             break;
     94 
     95         case OVS_ACTION_ATTR_RECIRC:
     96             break;
     97 
     98         case OVS_ACTION_ATTR_PUSH_MPLS: {
     99             const struct ovs_action_push_mpls *mpls = nla_data(a);
    100 
    101             if (!eth_p_mpls(mpls->mpls_ethertype))
    102                 return -EINVAL;
    103             /* Prohibit push MPLS other than to a white list
    104              * for packets that have a known tag order.
    105              */
    106             if (vlan_tci & htons(VLAN_TAG_PRESENT) ||
    107                 (eth_type != htons(ETH_P_IP) &&
    108                  eth_type != htons(ETH_P_IPV6) &&
    109                  eth_type != htons(ETH_P_ARP) &&
    110                  eth_type != htons(ETH_P_RARP) &&
    111                  !eth_p_mpls(eth_type)))
    112                 return -EINVAL;
    113             eth_type = mpls->mpls_ethertype;
    114             break;
    115         }
    116 
    117         case OVS_ACTION_ATTR_POP_MPLS:
    118             if (vlan_tci & htons(VLAN_TAG_PRESENT) ||
    119                 !eth_p_mpls(eth_type))
    120                 return -EINVAL;
    121 
    122             /* Disallow subsequent L2.5+ set and mpls_pop actions
    123              * as there is no check here to ensure that the new
    124              * eth_type is valid and thus set actions could
    125              * write off the end of the packet or otherwise
    126              * corrupt it.
    127              *
    128              * Support for these actions is planned using packet
    129              * recirculation.
    130              */
    131             eth_type = htons(0);
    132             break;
    133 
    134         case OVS_ACTION_ATTR_SET:
    135             err = validate_set(a, key, sfa,
    136                        &skip_copy, mac_proto, eth_type,
    137                        false, log);
    138             if (err)
    139                 return err;
    140             break;
    141 
    142         case OVS_ACTION_ATTR_SET_MASKED:
    143             err = validate_set(a, key, sfa,
    144                        &skip_copy, mac_proto, eth_type,
    145                        true, log);
    146             if (err)
    147                 return err;
    148             break;
    149 
    150         case OVS_ACTION_ATTR_SAMPLE: {
    151             bool last = nla_is_last(a, rem);
    152 
    153             err = validate_and_copy_sample(net, a, key, sfa,
    154                                eth_type, vlan_tci,
    155                                log, last);
    156             if (err)
    157                 return err;
    158             skip_copy = true;
    159             break;
    160         }
    161 
    162         case OVS_ACTION_ATTR_CT:
    163             err = ovs_ct_copy_action(net, a, key, sfa, log);
    164             if (err)
    165                 return err;
    166             skip_copy = true;
    167             break;
    168 
    169         case OVS_ACTION_ATTR_CT_CLEAR:
    170             break;
    171 
    172         case OVS_ACTION_ATTR_PUSH_ETH:
    173             /* Disallow pushing an Ethernet header if one
    174              * is already present */
    175             if (mac_proto != MAC_PROTO_NONE)
    176                 return -EINVAL;
    177             mac_proto = MAC_PROTO_NONE;
    178             break;
    179 
    180         case OVS_ACTION_ATTR_POP_ETH:
    181             if (mac_proto != MAC_PROTO_ETHERNET)
    182                 return -EINVAL;
    183             if (vlan_tci & htons(VLAN_TAG_PRESENT))
    184                 return -EINVAL;
    185             mac_proto = MAC_PROTO_ETHERNET;
    186             break;
    187 
    188         case OVS_ACTION_ATTR_PUSH_NSH:
    189             if (mac_proto != MAC_PROTO_ETHERNET) {
    190                 u8 next_proto;
    191 
    192                 next_proto = tun_p_from_eth_p(eth_type);
    193                 if (!next_proto)
    194                     return -EINVAL;
    195             }
    196             mac_proto = MAC_PROTO_NONE;
    197             if (!validate_nsh(nla_data(a), false, true, true))
    198                 return -EINVAL;
    199             break;
    200 
    201         case OVS_ACTION_ATTR_POP_NSH: {
    202             __be16 inner_proto;
    203 
    204             if (eth_type != htons(ETH_P_NSH))
    205                 return -EINVAL;
    206             inner_proto = tun_p_to_eth_p(key->nsh.base.np);
    207             if (!inner_proto)
    208                 return -EINVAL;
    209             if (key->nsh.base.np == TUN_P_ETHERNET)
    210                 mac_proto = MAC_PROTO_ETHERNET;
    211             else
    212                 mac_proto = MAC_PROTO_NONE;
    213             break;
    214         }
    215 
    216         default:
    217             OVS_NLERR(log, "Unknown Action type %d", type);
    218             return -EINVAL;
    219         }
    220         if (!skip_copy) {
    221             err = copy_action(a, sfa, log);
    222             if (err)
    223                 return err;
    224         }
    225     }
    226 
    227     if (rem > 0)
    228         return -EINVAL;
    229 
    230     return 0;
    231 }

    调试信息:

    场景一:

    流表:
    ovs-ofctl add-flow aaa 'table=0, in_port=veth2 actions=push_mpls:0x8847,set_mpls_label:800,resubmit(,10)' -O openflow15
    ovs-ofctl add-flow aaa 'table=10, mpls, mpls_label=800 actions=pop_mpls:0x0800,mod_dl_src=fe:22:33:44:55:66,mod_dl_dst=11:22:33:44:55:66,output:veth3' -O openflow15
    
    调试信息:
    3月 20 16:18:30 localhost.localdomain kernel: ovs_flow_cmd_new ... ...
    
    3月 20 16:18:30 localhost.localdomain kernel: nla_for_each_nested, type=3, key_len=12
    3月 20 16:18:30 localhost.localdomain kernel: nla_for_each_nested, type=1, key_len=-1
    3月 20 16:18:30 localhost.localdomain kernel: type: 3, key_len=12
    3月 20 16:18:30 localhost.localdomain kernel: OVS_ACTION_ATTR_SET
    3月 20 16:18:30 localhost.localdomain kernel: type: 1, key_len=-1
    3月 20 16:18:30 localhost.localdomain kernel: OVS_ACTION_ATTR_OUTPUT
    3月 20 16:18:30 localhost.localdomain kernel: nla_for_each_nested, type=3, key_len=12
    3月 20 16:18:30 localhost.localdomain kernel: nla_for_each_nested, type=1, key_len=-1
    3月 20 16:18:30 localhost.localdomain kernel: type: 3, key_len=12
    3月 20 16:18:30 localhost.localdomain kernel: OVS_ACTION_ATTR_SET
    3月 20 16:18:30 localhost.localdomain kernel: type: 1, key_len=-1
    3月 20 16:18:30 localhost.localdomain kernel: OVS_ACTION_ATTR_OUTPUT
    3月 20 16:18:30 localhost.localdomain kernel: do_execute_actions, type: 20
    3月 20 16:18:30 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_SET_TO_MASKED
    3月 20 16:18:30 localhost.localdomain kernel: do_execute_actions, type: 1
    3月 20 16:18:30 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_OUTPUT
    3月 20 16:18:30 localhost.localdomain kernel: not find ovs flows ... ...
    3月 20 16:18:30 localhost.localdomain kernel: queue_userspace_packet ... ...
    3月 20 16:18:30 localhost.localdomain kernel: ovs_flow_cmd_new ... ...

    场景二:

    流表:
    ovs-ofctl add-flow aaa 'table=0, in_port=veth2 actions=push_mpls:0x8847,set_mpls_label:800,output:veth3' -O openflow15
    ovs-ofctl add-flow aaa 'table=0, in_port=veth4, mpls, mpls_label=800 actions=pop_mpls:0x0800,mod_dl_src=fe:22:33:44:55:66,mod_dl_dst=11:22:33:44:55:66,output:veth5' -O openflow15
    
    调试信息:
    3月 20 16:30:27 localhost.localdomain kernel: ovs_flow_cmd_new ... ...
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=9, key_len=12796
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=1, key_len=-1
    3月 20 16:30:27 localhost.localdomain kernel: type: 9, key_len=12796
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_PUSH_MPLS
    3月 20 16:30:27 localhost.localdomain kernel: type: 1, key_len=-1
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_OUTPUT
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=9, key_len=12796
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=1, key_len=-1
    3月 20 16:30:27 localhost.localdomain kernel: type: 9, key_len=12796
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_PUSH_MPLS
    3月 20 16:30:27 localhost.localdomain kernel: type: 1, key_len=-1
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_OUTPUT
    3月 20 16:30:27 localhost.localdomain kernel: do_execute_actions, type: 9
    3月 20 16:30:27 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_PUSH_MPLS
    3月 20 16:30:27 localhost.localdomain kernel: do_execute_actions, type: 1
    3月 20 16:30:27 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_OUTPUT
    3月 20 16:30:27 localhost.localdomain kernel: not find ovs flows ... ...
    3月 20 16:30:27 localhost.localdomain kernel: queue_userspace_packet ... ...
    3月 20 16:30:27 localhost.localdomain kernel: ovs_flow_cmd_new ... ...
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=3, key_len=12
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=10, key_len=4
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=1, key_len=1
    3月 20 16:30:27 localhost.localdomain kernel: type: 3, key_len=12
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_SET
    3月 20 16:30:27 localhost.localdomain kernel: type: 10, key_len=4
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_POP_MPLS
    3月 20 16:30:27 localhost.localdomain kernel: type: 1, key_len=1
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_OUTPUT
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=3, key_len=12
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=10, key_len=4
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=1, key_len=1
    3月 20 16:30:27 localhost.localdomain kernel: type: 3, key_len=12
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_SET
    3月 20 16:30:27 localhost.localdomain kernel: type: 10, key_len=4
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_POP_MPLS
    3月 20 16:30:27 localhost.localdomain kernel: type: 1, key_len=1
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_OUTPUT
    3月 20 16:30:27 localhost.localdomain kernel: do_execute_actions, type: 20
    3月 20 16:30:27 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_SET_TO_MASKED
    3月 20 16:30:27 localhost.localdomain kernel: do_execute_actions, type: 10
    3月 20 16:30:27 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_POP_MPLS
    3月 20 16:30:27 localhost.localdomain kernel: do_execute_actions, type: 1
    3月 20 16:30:27 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_OUTPUT
    3月 20 16:30:27 localhost.localdomain kernel: not find ovs flows ... ...
    3月 20 16:30:27 localhost.localdomain kernel: queue_userspace_packet ... ...

    总结:

    以上以mpls封装解封装为例(或push_vlan,pop_vlan,push_nsh,pop_nsh,push_eth,pop_eth等)

    从场景一和场景二得出结论:

    流表从in到out中间的过程,如果同时存在push和pop动作,ovs会跳过push和pop动作的处理,不会copy到kernel的流表项中

  • 相关阅读:
    单链表相关笔试题:单链表逆转,约瑟夫环等
    cURL安装和使用笔记
    WSDL中文版——详解
    [c++语法]类
    spark源码解析之基本概念
    apache-spark导入eclipse环境
    zookeeper应用实例
    spring容器加载完毕做一件事情(利用ContextRefreshedEvent事件)
    Let's do our own full blown HTTP server with Netty--转载
    1号店11.11:从应用架构落地点谈高可用高并发高性能--转载
  • 原文地址:https://www.cnblogs.com/wangjq19920210/p/10564531.html
Copyright © 2011-2022 走看看