On Mon, Oct 21, 2024 at 7:03 AM Aleksandr Smirnov <[email protected]> wrote:
>
> This is RFC proposal, the code below is a working prototype, unit test is not 
> ready to look into.
>
> 1. Introduction
>
> The objective is to enchance routing policies to organize them as set of 
> independent lists,
> here 'chains', and allow to select and traverse chains depending on match 
> conditions.
>
> Every routing policy rule have assigned chain name, a type of string, or an 
> empty string.
> Rule actions have new action 'jump' with string argument that allows to switch
> rule's traversal to given chain.
>
> 2. New traversal flow.
>
> The flow starts rule's traversal for only those having an empty chain name,
> accoring to their priorities.
> If match occurs on rule having the 'jump' action, a traversal restarts for 
> rules
> that belongs to that chain, again, accoring to their priorities.
> Any other actions will stop router policy flow.
> (i.e. 'jump' have meaning of 'goto' but not 'call/return').
>
> 3. Change of utilities
>
> ovn-nbctl is changed to accept and report new options.
>
> ovn-nbctl lr-policy-add accepts chain name as optional argument.
>
>     ovn-nbctl [--chain Name] lr-policy-add ...
>
>     If omitted, chain name will be empty (i.e. rule added will belong to 
> default flow)
>
> ovn-nbctl lr-policy-add accepts new action 'jump'
>
>     ovn-nbctl lr-policy-add ... jump Name
>
> ovn-nbctl lr-policy-list changes its output format
>     to print chain name in first column
>     to print jump actions
>
> 4. Changes in NB DB schema
>
> Logical_Router_Policy:
>     New field:
>         Name: chain
>         Type: string
>     New field:
>         Name: jump_chain
>         Type: string
>     Modified field:
>         Name: actions
>         Value: add enum value 'jump'
>
> 5. Change in the SB DB generation
>
>     1. Reserve one 16 bit register to hold chain ID numeric value
>        designating current chain to traverse (here for example Rx[0..15])
>     2. Reserve new stage at LR, ingress, to make initial assignment to 
> Rx[0..15] := 0
>     3. Generate router policy flow in the following manner:
>         3.1 lr_in_ip_routing_ecmp  (not changed)
>         3.2 lr_in_policy_pre
>                 match:  1
>                 actoin: Rx[0..15] = 0; next;
>         3.3 lr_in_policy
>                 match: (Rx[0..15] == <chain_id>) && (<nb:match>)
>                 action: <nb:action_not_jump>
>                         | 'Rx[0..15] = <jump_chain_id>; next(ingress, 
> lr_in_policy);'
>
> Signed-off-by: Aleksandr Smirnov <[email protected]>
> ---
> RFC: First post.

Thanks Aleksandr. This idea looks good to me in general. I didn't
review in much detail since it is RFC. Just some reminders:
- We need to document the register usage carefully and make sure it
does not conflict with other features for the router pipeline.
- Do we need a mechanism to avoid looping forever in the chains?
Probably by maintaining a counter of jumps and check if it reaches the
max allowed count then drop?

Regards,
Han

> ---
>  northd/northd.c       | 68 ++++++++++++++++++++++++++++++++++++++++---
>  northd/northd.h       | 19 ++++++------
>  ovn-nb.ovsschema      |  8 +++--
>  ovn-nb.xml            | 21 ++++++++++++-
>  tests/ovn-nbctl.at    | 17 +++++++++--
>  tests/ovn-northd.at   | 14 ++++++++-
>  utilities/ovn-nbctl.c | 56 ++++++++++++++++++++++++++++-------
>  7 files changed, 172 insertions(+), 31 deletions(-)
>
> diff --git a/northd/northd.c b/northd/northd.c
> index 0fe15ac59..0639b4881 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -189,6 +189,7 @@ BUILD_ASSERT_DECL(ACL_OBS_STAGE_MAX < (1 << 2));
>  #define REG_SRC_IPV4 "reg1"
>  #define REG_SRC_IPV6 "xxreg1"
>  #define REG_DHCP_RELAY_DIP_IPV4 "reg2"
> +#define REG_POLICY_CHAIN_ID "reg6[0..15]"
>  #define REG_ROUTE_TABLE_ID "reg7"
>
>  /* Register used to store backend ipv6 address
> @@ -10756,11 +10757,50 @@ static bool check_bfd_state(const struct 
> nbrec_logical_router_policy *rule,
>      return true;
>  }
>
> +
> +
> +static uint32_t
> +policy_chain_add(struct simap *chain_ids,
> +                 const char *chain_name)
> +{
> +    uint32_t id = simap_count(chain_ids) + 1;
> +
> +    if (id == UINT16_MAX) {
> +        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> +        VLOG_WARN_RL(&rl, "too many policy chains for Logical Router.");
> +        return 0;
> +    }
> +
> +    if (!simap_put(chain_ids, chain_name, id)) {
> +        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> +        VLOG_WARN_RL(&rl, "Policy chain id unexpectedly appeared");
> +    }
> +
> +    return id;
> +}
> +
> +static uint32_t
> +policy_chain_id(struct simap *chain_ids,
> +                const char *chain_name)
> +{
> +    if (!chain_name || !chain_name[0]) {
> +        return 0;
> +    }
> +
> +    uint32_t id = simap_get(chain_ids, chain_name);
> +    if (!id) {
> +        id = policy_chain_add(chain_ids, chain_name);
> +    }
> +
> +    return id;
> +}
> +
>  static void
>  build_routing_policy_flow(struct lflow_table *lflows, struct ovn_datapath 
> *od,
>                            const struct hmap *lr_ports, struct route_policy 
> *rp,
>                            const struct ovsdb_idl_row *stage_hint,
> -                          struct lflow_ref *lflow_ref)
> +                          struct lflow_ref *lflow_ref,
> +                          struct simap *chain_ids)
>  {
>      const struct nbrec_logical_router_policy *rule = rp->rule;
>      struct ds match = DS_EMPTY_INITIALIZER;
> @@ -10808,7 +10848,12 @@ build_routing_policy_flow(struct lflow_table 
> *lflows, struct ovn_datapath *od,
>                        lrp_addr_s,
>                        out_port->lrp_networks.ea_s,
>                        out_port->json_key);
> -
> +    } else if (!strcmp(rule->action, "jump")) {
> +        ds_put_format(&actions,
> +                      "%s=%d; next(pipeline=ingress,table=%d);",
> +                      REG_POLICY_CHAIN_ID,
> +                      policy_chain_id(chain_ids, rule->jump_chain),
> +                      ovn_stage_get_table(S_ROUTER_IN_POLICY));
>      } else if (!strcmp(rule->action, "drop")) {
>          ds_put_cstr(&actions, debug_drop_action());
>      } else if (!strcmp(rule->action, "allow")) {
> @@ -10818,7 +10863,9 @@ build_routing_policy_flow(struct lflow_table *lflows, 
> struct ovn_datapath *od,
>          }
>          ds_put_cstr(&actions, REG_ECMP_GROUP_ID" = 0; next;");
>      }
> -    ds_put_format(&match, "%s", rule->match);
> +
> +    ds_put_format(&match, "%s == %d && (%s)", REG_POLICY_CHAIN_ID,
> +                  policy_chain_id(chain_ids, rule->chain), rule->match);
>
>      ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_POLICY, rule->priority,
>                              ds_cstr(&match), ds_cstr(&actions), stage_hint,
> @@ -13804,9 +13851,15 @@ build_ingress_policy_flows_for_lrouter(
>      ovs_assert(od->nbr);
>      /* This is a catch-all rule. It has the lowest priority (0)
>       * does a match-all("1") and pass-through (next) */
> +
>      ovn_lflow_add(lflows, od, S_ROUTER_IN_POLICY, 0, "1",
>                    REG_ECMP_GROUP_ID" = 0; next;",
>                    lflow_ref);
> +
> +    ovn_lflow_add(lflows, od, S_ROUTER_IN_POLICY_PRE, 0, "1",
> +                  REG_POLICY_CHAIN_ID" = 0; next;",
> +                  lflow_ref);
> +
>      ovn_lflow_add(lflows, od, S_ROUTER_IN_POLICY_ECMP, 150,
>                    REG_ECMP_GROUP_ID" == 0", "next;",
>                    lflow_ref);
> @@ -13816,6 +13869,10 @@ build_ingress_policy_flows_for_lrouter(
>      /* Convert routing policies to flows. */
>      uint16_t ecmp_group_id = 1;
>      struct route_policy *rp;
> +    struct simap chain_ids;
> +
> +    simap_init(&chain_ids);
> +
>      HMAP_FOR_EACH_WITH_HASH (rp, key_node, uuid_hash(&od->key),
>                               route_policies) {
>          const struct nbrec_logical_router_policy *rule = rp->rule;
> @@ -13828,9 +13885,12 @@ build_ingress_policy_flows_for_lrouter(
>              ecmp_group_id++;
>          } else {
>              build_routing_policy_flow(lflows, od, lr_ports, rp,
> -                                      &rule->header_, lflow_ref);
> +                                      &rule->header_, lflow_ref,
> +                                      &chain_ids);
>          }
>      }
> +
> +    simap_destroy(&chain_ids);
>  }
>
>  /* Local router ingress table ARP_RESOLVE: ARP Resolution. */
> diff --git a/northd/northd.h b/northd/northd.h
> index 8f76d642d..c711e2587 100644
> --- a/northd/northd.h
> +++ b/northd/northd.h
> @@ -491,17 +491,18 @@ enum ovn_stage {
>      PIPELINE_STAGE(ROUTER, IN,  IP_ROUTING_PRE,  13, "lr_in_ip_routing_pre") 
>  \
>      PIPELINE_STAGE(ROUTER, IN,  IP_ROUTING,      14, "lr_in_ip_routing")     
>  \
>      PIPELINE_STAGE(ROUTER, IN,  IP_ROUTING_ECMP, 15, 
> "lr_in_ip_routing_ecmp") \
> -    PIPELINE_STAGE(ROUTER, IN,  POLICY,          16, "lr_in_policy")         
>  \
> -    PIPELINE_STAGE(ROUTER, IN,  POLICY_ECMP,     17, "lr_in_policy_ecmp")    
>  \
> -    PIPELINE_STAGE(ROUTER, IN,  DHCP_RELAY_RESP_CHK, 18,                     
>  \
> +    PIPELINE_STAGE(ROUTER, IN,  POLICY_PRE,      16, "lr_in_policy_pre")     
>  \
> +    PIPELINE_STAGE(ROUTER, IN,  POLICY,          17, "lr_in_policy")         
>  \
> +    PIPELINE_STAGE(ROUTER, IN,  POLICY_ECMP,     18, "lr_in_policy_ecmp")    
>  \
> +    PIPELINE_STAGE(ROUTER, IN,  DHCP_RELAY_RESP_CHK, 19,                     
>  \
>                    "lr_in_dhcp_relay_resp_chk")                               
>  \
> -    PIPELINE_STAGE(ROUTER, IN,  DHCP_RELAY_RESP, 19,                         
>  \
> +    PIPELINE_STAGE(ROUTER, IN,  DHCP_RELAY_RESP, 20,                         
>  \
>                    "lr_in_dhcp_relay_resp")                                   
>  \
> -    PIPELINE_STAGE(ROUTER, IN,  ARP_RESOLVE,     20, "lr_in_arp_resolve")    
>  \
> -    PIPELINE_STAGE(ROUTER, IN,  CHK_PKT_LEN,     21, "lr_in_chk_pkt_len")    
>  \
> -    PIPELINE_STAGE(ROUTER, IN,  LARGER_PKTS,     22, "lr_in_larger_pkts")    
>  \
> -    PIPELINE_STAGE(ROUTER, IN,  GW_REDIRECT,     23, "lr_in_gw_redirect")    
>  \
> -    PIPELINE_STAGE(ROUTER, IN,  ARP_REQUEST,     24, "lr_in_arp_request")    
>  \
> +    PIPELINE_STAGE(ROUTER, IN,  ARP_RESOLVE,     21, "lr_in_arp_resolve")    
>  \
> +    PIPELINE_STAGE(ROUTER, IN,  CHK_PKT_LEN,     22, "lr_in_chk_pkt_len")    
>  \
> +    PIPELINE_STAGE(ROUTER, IN,  LARGER_PKTS,     23, "lr_in_larger_pkts")    
>  \
> +    PIPELINE_STAGE(ROUTER, IN,  GW_REDIRECT,     24, "lr_in_gw_redirect")    
>  \
> +    PIPELINE_STAGE(ROUTER, IN,  ARP_REQUEST,     25, "lr_in_arp_request")    
>  \
>                                                                        \
>      /* Logical router egress stages. */                               \
>      PIPELINE_STAGE(ROUTER, OUT, CHECK_DNAT_LOCAL,   0,                       
> \
> diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema
> index b4a395c56..b81647fa1 100644
> --- a/ovn-nb.ovsschema
> +++ b/ovn-nb.ovsschema
> @@ -1,7 +1,7 @@
>  {
>      "name": "OVN_Northbound",
> -    "version": "7.6.0",
> -    "cksum": "2171465655 38284",
> +    "version": "7.6.1",
> +    "cksum": "2213857026 38387",
>      "tables": {
>          "NB_Global": {
>              "columns": {
> @@ -518,10 +518,12 @@
>                  "priority": {"type": {"key": {"type": "integer",
>                                                "minInteger": 0,
>                                                "maxInteger": 32767}}},
> +                "chain": {"type": "string"},
>                  "match": {"type": "string"},
>                  "action": {"type": {
>                      "key": {"type": "string",
> -                            "enum": ["set", ["allow", "drop", "reroute"]]}}},
> +                            "enum": ["set", ["allow", "drop", "reroute", 
> "jump"]]}}},
> +                "jump_chain": {"type": "string"},
>                  "nexthop": {"type": {"key": "string", "min": 0, "max": 1}},
>                  "nexthops": {"type": {
>                      "key": "string", "min": 0, "max": "unlimited"}},
> diff --git a/ovn-nb.xml b/ovn-nb.xml
> index 2836f58f5..4476c7e7e 100644
> --- a/ovn-nb.xml
> +++ b/ovn-nb.xml
> @@ -3906,7 +3906,15 @@ or
>        <p>
>          The routing policy's priority.  Rules with numerically higher 
> priority
>          take precedence over those with lower. A rule is uniquely identified
> -        by the priority and match string.
> +        by the priority, chain and match string.
> +      </p>
> +    </column>
> +
> +    <column name="chain">
> +      <p>
> +        The routing policy rule's chain name. Only rules with empty chain 
> name are
> +        traversed by default. Others chains are traversed as responce to
> +        jump action.
>        </p>
>      </column>
>
> @@ -3941,9 +3949,20 @@ or
>            <code>reroute</code>: Reroute packet to <ref column="nexthop"/> or
>            <ref column="nexthops"/>.
>          </li>
> +
> +        <li>
> +          <code>jump</code>: Restart rules traversal for those having chain
> +          name equal to <ref column="jump_chain"/>.
> +        </li>
>        </ul>
>      </column>
>
> +    <column name="jump_chain">
> +      <p>
> +        The routing policy rule's chain name selected to traverse.
> +      </p>
> +    </column>
> +
>      <column name="nexthop">
>        <p>
>          Note: This column is deprecated in favor of <ref column="nexthops"/>.
> diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
> index 2efa13b93..7795d5ed4 100644
> --- a/tests/ovn-nbctl.at
> +++ b/tests/ovn-nbctl.at
> @@ -2288,11 +2288,22 @@ OVN_NBCTL_TEST([ovn_nbctl_policies], [policies], [
>  AT_CHECK([ovn-nbctl lr-add lr0])
>
>  dnl Add policies with allow and drop actions
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.1.0/24" drop])
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 100 "ip4.src == 1.1.2.0/24" allow 
> pkt_mark=100,foo=bar])
> +AT_CHECK([ovn-nbctl --chain "inbound" lr-policy-add lr0 100 "ip4.src == 
> 1.1.1.0/24" drop])
> +AT_CHECK([ovn-nbctl --chain "outbound" lr-policy-add lr0 100 "ip4.src == 
> 2.1.1.0/24" allow])
> +AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.2.0/24" jump 
> "inbound"])
> +AT_CHECK([ovn-nbctl --chain "inbound" lr-policy-add lr0 101 "ip4.src == 
> 1.1.2.0/24" allow pkt_mark=100,foo=bar])
> +AT_CHECK([ovn-nbctl lr-policy-add lr0 11 "ip6.src == 2002::/64" jump 
> "outbound"])
> +
> +ovn-nbctl list Logical_Router_Policy
> +ovn-nbctl lr-policy-list lr0
> +
>  AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.1.0/24" allow])
>  AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.2.0/24" drop])
> -AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip6.src == 2002::/64" drop])
> +
> +
> +
> +
> +
>  AT_CHECK([ovn-nbctl --bfd lr-policy-add lr0 103 "ip4.src == 1.2.3.0/24" 
> reroute 192.168.1.1], [1], [],
>    [ovn-nbctl: out lrp not found for 192.168.1.1 nexthop
>  ])
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index d6a8c4640..f423242b9 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -3419,7 +3419,19 @@ check ovn-nbctl lsp-set-type public-lr0 router
>  check ovn-nbctl lsp-set-addresses public-lr0 router
>  check ovn-nbctl lsp-set-options public-lr0 router-port=lr0-public
>
> -check ovn-nbctl --wait=sb lr-policy-add lr0  10 "ip4.src == 10.0.0.3" 
> reroute 172.168.0.101,172.168.0.102
> +###check ovn-nbctl --wait=sb lr-policy-add lr0  10 "ip4.src == 10.0.0.3" 
> reroute 172.168.0.101,172.168.0.102
> +
> +AT_CHECK([ovn-nbctl --chain "inbound" lr-policy-add lr0 100 "ip4.src == 
> 1.1.1.0/24" drop])
> +AT_CHECK([ovn-nbctl --chain "inbound" lr-policy-add lr0 100 "ip4.src == 
> 1.1.2.0/24" allow pkt_mark=100,foo=bar])
> +AT_CHECK([ovn-nbctl --chain "outbound" lr-policy-add lr0 101 "ip4.src == 
> 2.1.1.0/24" allow])
> +AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip4.src == 2.1.2.0/24" jump 
> "inbound"])
> +AT_CHECK([ovn-nbctl lr-policy-add lr0 101 "ip6.src == 2002::/64" jump 
> "outbound"])
> +
> +ovn-nbctl list Logical_Router_Policy
> +
> +sleep 1
> +
> +ovn-sbctl lflow-list lr0
>
>  ovn-nbctl lr-policy-list lr0 > policy-list
>  AT_CAPTURE_FILE([policy-list])
> diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
> index d45be75c7..13277db66 100644
> --- a/utilities/ovn-nbctl.c
> +++ b/utilities/ovn-nbctl.c
> @@ -4116,11 +4116,13 @@ nbctl_lr_policy_add(struct ctl_context *ctx)
>      char **nexthops = NULL;
>
>      bool reroute = false;
> +    bool jump = false;
> +
>      /* Validate action. */
>      if (strcmp(action, "allow") && strcmp(action, "drop")
> -        && strcmp(action, "reroute")) {
> +        && strcmp(action, "jump") && strcmp(action, "reroute")) {
>          ctl_error(ctx, "%s: action must be one of \"allow\", \"drop\", "
> -                  "and \"reroute\"", action);
> +                  "\"reroute\", \"jump\"", action);
>          return;
>      }
>      if (!strcmp(action, "reroute")) {
> @@ -4131,6 +4133,14 @@ nbctl_lr_policy_add(struct ctl_context *ctx)
>          reroute = true;
>      }
>
> +    if (!strcmp(action, "jump")) {
> +        if (ctx->argc < 6) {
> +            ctl_error(ctx, "Chain number is required when action is jump.");
> +            return;
> +        }
> +        jump = true;
> +    }
> +
>      /* Check if same routing policy already exists.
>       * A policy is uniquely identified by priority and match */
>      bool may_exist = !!shash_find(&ctx->options, "--may-exist");
> @@ -4195,11 +4205,22 @@ nbctl_lr_policy_add(struct ctl_context *ctx)
>          free(nexthops_arg);
>      }
>
> +    const char *chain_s = shash_find_data(&ctx->options, "--chain");
> +
>      struct nbrec_logical_router_policy *policy;
>      policy = nbrec_logical_router_policy_insert(ctx->txn);
>      nbrec_logical_router_policy_set_priority(policy, priority);
>      nbrec_logical_router_policy_set_match(policy, ctx->argv[3]);
>      nbrec_logical_router_policy_set_action(policy, action);
> +
> +    if (chain_s) {
> +        nbrec_logical_router_policy_set_chain(policy, chain_s);
> +    }
> +
> +    if (jump) {
> +        nbrec_logical_router_policy_set_jump_chain(policy, ctx->argv[5]);
> +    }
> +
>      if (reroute) {
>          nbrec_logical_router_policy_set_nexthops(
>              policy, (const char **)nexthops, n_nexthops);
> @@ -4207,7 +4228,7 @@ nbctl_lr_policy_add(struct ctl_context *ctx)
>
>      /* Parse the options. */
>      struct smap options = SMAP_INITIALIZER(&options);
> -    for (i = reroute ? 6 : 5; i < ctx->argc; i++) {
> +    for (i = (reroute | jump) ? 6 : 5; i < ctx->argc; i++) {
>          char *key, *value;
>          value = xstrdup(ctx->argv[i]);
>          key = strsep(&value, "=");
> @@ -4394,9 +4415,10 @@ nbctl_lr_policy_del(struct ctl_context *ctx)
>      }
>  }
>
> - struct routing_policy {
> +struct routing_policy {
>      int priority;
>      char *match;
> +    char *chain;
>      const struct nbrec_logical_router_policy *policy;
>  };
>
> @@ -4405,6 +4427,13 @@ routing_policy_cmp(const void *policy1_, const void 
> *policy2_)
>  {
>      const struct routing_policy *policy1p = policy1_;
>      const struct routing_policy *policy2p = policy2_;
> +
> +    int chain_match = strcmp(policy1p->chain, policy2p->chain);
> +
> +    if (chain_match) {
> +        return chain_match;
> +    }
> +
>      if (policy1p->priority != policy2p->priority) {
>          return policy1p->priority > policy2p->priority ? -1 : 1;
>      } else {
> @@ -4416,17 +4445,21 @@ static void
>  print_routing_policy(const struct nbrec_logical_router_policy *policy,
>                       struct ds *s)
>  {
> +    ds_put_format(s, "%25s %10"PRId64" %50s %15s",
> +                  (*policy->chain) ? policy->chain : "",
> +                  policy->priority, policy->match, policy->action);
> +
> +    if (strcmp(policy->action, "jump") == 0
> +        && *policy->jump_chain) {
> +        ds_put_format(s, " %s", policy->jump_chain);
> +    }
> +
>      if (policy->n_nexthops) {
> -        ds_put_format(s, "%10"PRId64" %50s %15s", policy->priority,
> -                      policy->match, policy->action);
>          for (int i = 0; i < policy->n_nexthops; i++) {
>              char *next_hop = normalize_prefix_str(policy->nexthops[i]);
>              ds_put_format(s, i ? ", %s" : " %25s", next_hop ? next_hop : "");
>              free(next_hop);
>          }
> -    } else {
> -        ds_put_format(s, "%10"PRId64" %50s %15s", policy->priority,
> -                      policy->match, policy->action);
>      }
>
>      if (!smap_is_empty(&policy->options) || policy->n_bfd_sessions) {
> @@ -4457,6 +4490,8 @@ nbctl_pre_lr_policy_list(struct ctl_context *ctx)
>      ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_options);
>      ovsdb_idl_add_column(ctx->idl,
>                           &nbrec_logical_router_policy_col_bfd_sessions);
> +    ovsdb_idl_add_column(ctx->idl, &nbrec_logical_router_policy_col_chain);
> +    ovsdb_idl_add_column(ctx->idl, 
> &nbrec_logical_router_policy_col_jump_chain);
>  }
>
>  static void
> @@ -4476,6 +4511,7 @@ nbctl_lr_policy_list(struct ctl_context *ctx)
>              = lr->policies[i];
>          policies[n_policies].priority = policy->priority;
>          policies[n_policies].match = policy->match;
> +        policies[n_policies].chain = policy->chain;
>          policies[n_policies].policy = policy;
>          n_policies++;
>      }
> @@ -8100,7 +8136,7 @@ static const struct ctl_command_syntax nbctl_commands[] 
> = {
>      /* Policy commands */
>      { "lr-policy-add", 4, INT_MAX,
>       "ROUTER PRIORITY MATCH ACTION [NEXTHOP] [OPTIONS - KEY=VALUE ...]",
> -     nbctl_pre_lr_policy_add, nbctl_lr_policy_add, NULL, 
> "--may-exist,--bfd?",
> +     nbctl_pre_lr_policy_add, nbctl_lr_policy_add, NULL, 
> "--may-exist,--bfd?,--chain=",
>       RW },
>      { "lr-policy-del", 1, 3, "ROUTER [{PRIORITY | UUID} [MATCH]]",
>        nbctl_pre_lr_policy_del, nbctl_lr_policy_del, NULL, "--if-exists", RW 
> },
> --
> 2.47.0
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to