[ovs-dev] [PATCH v3] ofproto: New action TTL decrement.

Ben Pfaff blp at nicira.com
Sat Jan 14 01:17:06 UTC 2012


In the new documentation, invalid_ttl should be bold instead of
italic, because it is a literal string.  If you fix that, then this
looks good.  Thank you!

On Fri, Jan 13, 2012 at 05:13:48PM -0800, Pravin B Shelar wrote:
> Fixed according to comments from Ben.
> 
> v2-v3:
>         - Updated ovs-ofctl monitor documentation.
> v1-v2:
>         - Fixed man page
>         - Added invalid-ttl arg for ofctl-monitor.
>         - Added invalid-ttl packet-in test case.
> 
> --8<--------------------------cut here-------------------------->8-
> Following patch implements dec_ttl as vendor action with similar
> semantics as OpenFlow 1.2. If TTL reaches zero while procession
> actions in current table, the remaining actions in previous tables
> are processed. An configuration parameter is added to make TTL
> decrement to zero generate packet in.
> 
> Feature #8758
> ---
>  NEWS                          |    1 +
>  include/openflow/nicira-ext.h |    3 +-
>  include/openflow/openflow.h   |    9 ++++++-
>  lib/ofp-parse.c               |    4 +++
>  lib/ofp-print.c               |   24 ++++++++++++++++++--
>  lib/ofp-util.c                |    1 +
>  lib/ofp-util.def              |    1 +
>  lib/ofp-util.h                |    2 +-
>  ofproto/connmgr.c             |   46 ++++++++++++++++++++++++++++++++++++----
>  ofproto/connmgr.h             |    3 ++
>  ofproto/ofproto-dpif.c        |   36 +++++++++++++++++++++++++++++--
>  ofproto/ofproto.c             |    9 +++++++-
>  tests/ofp-print.at            |    2 +-
>  tests/ofproto-dpif.at         |   38 +++++++++++++++++++++++++++++++--
>  utilities/ovs-ofctl.8.in      |   19 ++++++++++++++++-
>  utilities/ovs-ofctl.c         |   36 +++++++++++++++++++++++++++++++-
>  16 files changed, 212 insertions(+), 22 deletions(-)
> 
> diff --git a/NEWS b/NEWS
> index b628e29..4f29e19 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -8,6 +8,7 @@ v1.5.0 - xx xxx xxxx
>          - Added support for querying, modifying, and deleting flows
>            based on flow cookie when using NXM.
>          - Added new NXM_PACKET_IN format.
> +        - Added new NXAST_DEC_TTL action.
>      - ovs-ofctl:
>          - Added daemonization support to the monitor and snoop commands.
>      - ovs-vsctl:
> diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
> index f00f994..e17b313 100644
> --- a/include/openflow/nicira-ext.h
> +++ b/include/openflow/nicira-ext.h
> @@ -361,7 +361,8 @@ enum nx_action_subtype {
>      NXAST_RESUBMIT_TABLE,       /* struct nx_action_resubmit */
>      NXAST_OUTPUT_REG,           /* struct nx_action_output_reg */
>      NXAST_LEARN,                /* struct nx_action_learn */
> -    NXAST_EXIT                  /* struct nx_action_header */
> +    NXAST_EXIT,                 /* struct nx_action_header */
> +    NXAST_DEC_TTL,              /* struct nx_action_header */
>  };
>  
>  /* Header for Nicira-defined actions. */
> diff --git a/include/openflow/openflow.h b/include/openflow/openflow.h
> index f68a140..cd30d32 100644
> --- a/include/openflow/openflow.h
> +++ b/include/openflow/openflow.h
> @@ -136,7 +136,11 @@ enum ofp_config_flags {
>      OFPC_FRAG_DROP     = 1,  /* Drop fragments. */
>      OFPC_FRAG_REASM    = 2,  /* Reassemble (only if OFPC_IP_REASM set). */
>      OFPC_FRAG_NX_MATCH = 3,  /* Make first fragments available for matching. */
> -    OFPC_FRAG_MASK     = 3
> +    OFPC_FRAG_MASK     = 3,
> +
> +    /* TTL processing - applicable for IP and MPLS packets. */
> +    OFPC_INVALID_TTL_TO_CONTROLLER = 1 << 2, /* Send packets with invalid TTL
> +                                                to the controller. */
>  };
>  
>  /* Switch configuration. */
> @@ -289,7 +293,8 @@ OFP_ASSERT(sizeof(struct ofp_port_mod) == 32);
>  /* Why is this packet being sent to the controller? */
>  enum ofp_packet_in_reason {
>      OFPR_NO_MATCH,          /* No matching flow. */
> -    OFPR_ACTION             /* Action explicitly output to controller. */
> +    OFPR_ACTION,            /* Action explicitly output to controller. */
> +    OFPR_INVALID_TTL        /* Packet has invalid TTL. */
>  };
>  
>  /* Packet received on port (datapath -> controller). */
> diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
> index 38c3dab..5321364 100644
> --- a/lib/ofp-parse.c
> +++ b/lib/ofp-parse.c
> @@ -364,6 +364,10 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
>      case OFPUTIL_NXAST_EXIT:
>          ofputil_put_NXAST_EXIT(b);
>          break;
> +
> +    case OFPUTIL_NXAST_DEC_TTL:
> +        ofputil_put_NXAST_DEC_TTL(b);
> +        break;
>      }
>  }
>  
> diff --git a/lib/ofp-print.c b/lib/ofp-print.c
> index aff12b6..0775ea6 100644
> --- a/lib/ofp-print.c
> +++ b/lib/ofp-print.c
> @@ -120,10 +120,19 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh,
>          }
>      }
>  
> -    if (pin.reason == OFPR_ACTION) {
> +    switch (pin.reason) {
> +    case OFPR_NO_MATCH:
> +        ds_put_cstr(string, " (via no_match)");
> +        break;
> +    case OFPR_ACTION:
>          ds_put_cstr(string, " (via action)");
> -    } else if (pin.reason != OFPR_NO_MATCH) {
> +        break;
> +    case OFPR_INVALID_TTL:
> +        ds_put_cstr(string, " (via invalid_ttl)");
> +        break;
> +      default:
>          ds_put_format(string, " (***reason %"PRIu8"***)", pin.reason);
> +        break;
>      }
>  
>      ds_put_format(string, " data_len=%zu", pin.packet_len);
> @@ -333,6 +342,10 @@ ofp_print_action(struct ds *s, const union ofp_action *a,
>          learn_format((const struct nx_action_learn *) a, s);
>          break;
>  
> +    case OFPUTIL_NXAST_DEC_TTL:
> +        ds_put_cstr(s, "dec_ttl");
> +        break;
> +
>      case OFPUTIL_NXAST_EXIT:
>          ds_put_cstr(s, "exit");
>          break;
> @@ -599,13 +612,18 @@ ofp_print_switch_features(struct ds *string,
>  static void
>  ofp_print_switch_config(struct ds *string, const struct ofp_switch_config *osc)
>  {
> -    uint16_t flags;
> +    enum ofp_config_flags flags;
>  
>      flags = ntohs(osc->flags);
>  
>      ds_put_format(string, " frags=%s", ofputil_frag_handling_to_string(flags));
>      flags &= ~OFPC_FRAG_MASK;
>  
> +    if (flags & OFPC_INVALID_TTL_TO_CONTROLLER) {
> +        ds_put_format(string, " invalid_ttl_to_controller");
> +        flags &= ~OFPC_INVALID_TTL_TO_CONTROLLER;
> +    }
> +
>      if (flags) {
>          ds_put_format(string, " ***unknown flags 0x%04"PRIx16"***", flags);
>      }
> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
> index b20d3fb..6fe1611 100644
> --- a/lib/ofp-util.c
> +++ b/lib/ofp-util.c
> @@ -2436,6 +2436,7 @@ validate_actions(const union ofp_action *actions, size_t n_actions,
>          case OFPUTIL_NXAST_NOTE:
>          case OFPUTIL_NXAST_SET_TUNNEL64:
>          case OFPUTIL_NXAST_EXIT:
> +        case OFPUTIL_NXAST_DEC_TTL:
>              break;
>          }
>  
> diff --git a/lib/ofp-util.def b/lib/ofp-util.def
> index 2958eb6..d05ec9d 100644
> --- a/lib/ofp-util.def
> +++ b/lib/ofp-util.def
> @@ -36,4 +36,5 @@ NXAST_ACTION(NXAST_RESUBMIT_TABLE, nx_action_resubmit,     0, NULL)
>  NXAST_ACTION(NXAST_OUTPUT_REG,     nx_action_output_reg,   0, NULL)
>  NXAST_ACTION(NXAST_LEARN,          nx_action_learn,        1, "learn")
>  NXAST_ACTION(NXAST_EXIT,           nx_action_header,       0, "exit")
> +NXAST_ACTION(NXAST_DEC_TTL,        nx_action_header,       0, "dec_ttl")
>  #undef NXAST_ACTION
> diff --git a/lib/ofp-util.h b/lib/ofp-util.h
> index d01e17a..422c14a 100644
> --- a/lib/ofp-util.h
> +++ b/lib/ofp-util.h
> @@ -227,7 +227,7 @@ struct ofputil_packet_in {
>      const void *packet;
>      size_t packet_len;
>  
> -    uint8_t reason;             /* One of OFPR_*. */
> +    enum ofp_packet_in_reason reason;    /* One of OFPRR_*. */
>      uint8_t table_id;
>      ovs_be64 cookie;
>  
> diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
> index 28d9488..887080a 100644
> --- a/ofproto/connmgr.c
> +++ b/ofproto/connmgr.c
> @@ -71,6 +71,8 @@ struct ofconn {
>  
>      /* type == OFCONN_PRIMARY only. */
>      enum nx_role role;           /* Role. */
> +    bool invalid_ttl_to_controller; /* Send packets with invalid TTL
> +                                       to the controller. */
>      struct hmap_node hmap_node;  /* In struct connmgr's "controllers" map. */
>      enum ofproto_band band;      /* In-band or out-of-band? */
>  };
> @@ -754,6 +756,18 @@ ofconn_set_role(struct ofconn *ofconn, enum nx_role role)
>      ofconn->role = role;
>  }
>  
> +void
> +ofconn_set_invalid_ttl_to_controller(struct ofconn *ofconn, bool val)
> +{
> +    ofconn->invalid_ttl_to_controller = val;
> +}
> +
> +bool
> +ofconn_get_invalid_ttl_to_controller(struct ofconn *ofconn)
> +{
> +    return ofconn->invalid_ttl_to_controller;
> +}
> +
>  /* Returns the currently configured flow format for 'ofconn', one of NXFF_*.
>   *
>   * The default, if no other format has been set, is NXFF_OPENFLOW10. */
> @@ -931,6 +945,7 @@ ofconn_create(struct connmgr *mgr, struct rconn *rconn, enum ofconn_type type)
>      ofconn->pktbuf = NULL;
>      ofconn->miss_send_len = 0;
>      ofconn->reply_counter = rconn_packet_counter_create ();
> +    ofconn->invalid_ttl_to_controller = false;
>      return ofconn;
>  }
>  
> @@ -1054,11 +1069,9 @@ ofconn_wait(struct ofconn *ofconn, bool handling_openflow)
>  
>  /* Returns true if 'ofconn' should receive asynchronous messages. */
>  static bool
> -ofconn_receives_async_msgs(const struct ofconn *ofconn)
> +ofconn_receives_async_msgs__(const struct ofconn *ofconn)
>  {
> -    if (!rconn_is_connected(ofconn->rconn)) {
> -        return false;
> -    } else if (ofconn->type == OFCONN_PRIMARY) {
> +    if (ofconn->type == OFCONN_PRIMARY) {
>          /* Primary controllers always get asynchronous messages unless they
>           * have configured themselves as "slaves".  */
>          return ofconn->role != NX_ROLE_SLAVE;
> @@ -1069,6 +1082,29 @@ ofconn_receives_async_msgs(const struct ofconn *ofconn)
>      }
>  }
>  
> +static bool
> +ofconn_receives_async_msgs(const struct ofconn *ofconn)
> +{
> +    if (!rconn_is_connected(ofconn->rconn)) {
> +        return false;
> +    } else {
> +        return ofconn_receives_async_msgs__(ofconn);
> +    }
> +}
> +
> +static bool
> +ofconn_interested_in_packet(const struct ofconn *ofconn,
> +                            const struct ofputil_packet_in *pin)
> +{
> +    if (!rconn_is_connected(ofconn->rconn)) {
> +        return false;
> +    } else if (pin->reason == OFPR_INVALID_TTL) {
> +        return ofconn->invalid_ttl_to_controller;
> +    } else {
> +        return ofconn_receives_async_msgs__(ofconn);
> +    }
> +}
> +
>  /* Returns a human-readable name for an OpenFlow connection between 'mgr' and
>   * 'target', suitable for use in log messages for identifying the connection.
>   *
> @@ -1178,7 +1214,7 @@ connmgr_send_packet_in(struct connmgr *mgr,
>      struct ofconn *ofconn;
>  
>      LIST_FOR_EACH (ofconn, node, &mgr->all_conns) {
> -        if (ofconn_receives_async_msgs(ofconn)) {
> +        if (ofconn_interested_in_packet(ofconn, pin)) {
>              schedule_packet_in(ofconn, *pin, flow);
>          }
>      }
> diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h
> index bbee7f4..8ff89f3 100644
> --- a/ofproto/connmgr.h
> +++ b/ofproto/connmgr.h
> @@ -92,6 +92,9 @@ void ofconn_set_packet_in_format(struct ofconn *, enum nx_packet_in_format);
>  bool ofconn_get_flow_mod_table_id(const struct ofconn *);
>  void ofconn_set_flow_mod_table_id(struct ofconn *, bool enable);
>  
> +void ofconn_set_invalid_ttl_to_controller(struct ofconn *, bool);
> +bool ofconn_get_invalid_ttl_to_controller(struct ofconn *);
> +
>  int ofconn_get_miss_send_len(const struct ofconn *);
>  void ofconn_set_miss_send_len(struct ofconn *, int miss_send_len);
>  
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index 6ecf71b..567240d 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -4291,7 +4291,8 @@ flood_packets(struct action_xlate_ctx *ctx, bool all)
>  }
>  
>  static void
> -execute_controller_action(struct action_xlate_ctx *ctx, int len)
> +execute_controller_action(struct action_xlate_ctx *ctx, int len,
> +                          enum ofp_packet_in_reason reason)
>  {
>      struct ofputil_packet_in pin;
>      struct ofpbuf *packet;
> @@ -4336,7 +4337,7 @@ execute_controller_action(struct action_xlate_ctx *ctx, int len)
>  
>      pin.packet = packet->data;
>      pin.packet_len = packet->size;
> -    pin.reason = OFPR_ACTION;
> +    pin.reason = reason;
>      pin.table_id = ctx->table_id;
>      pin.cookie = ctx->cookie;
>  
> @@ -4349,6 +4350,25 @@ execute_controller_action(struct action_xlate_ctx *ctx, int len)
>      ofpbuf_delete(packet);
>  }
>  
> +static bool
> +compose_dec_ttl(struct action_xlate_ctx *ctx)
> +{
> +    if (ctx->flow.dl_type != htons(ETH_TYPE_IP) &&
> +        ctx->flow.dl_type != htons(ETH_TYPE_IPV6)) {
> +        return false;
> +    }
> +
> +    if (ctx->flow.nw_ttl > 1) {
> +        ctx->flow.nw_ttl--;
> +        return false;
> +    } else {
> +        execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL);
> +
> +        /* Stop processing for current table. */
> +        return true;
> +    }
> +}
> +
>  static void
>  xlate_output_action__(struct action_xlate_ctx *ctx,
>                        uint16_t port, uint16_t max_len)
> @@ -4374,7 +4394,7 @@ xlate_output_action__(struct action_xlate_ctx *ctx,
>          flood_packets(ctx, true);
>          break;
>      case OFPP_CONTROLLER:
> -        execute_controller_action(ctx, max_len);
> +        execute_controller_action(ctx, max_len, OFPR_ACTION);
>          break;
>      case OFPP_LOCAL:
>          compose_output_action(ctx, OFPP_LOCAL);
> @@ -4730,12 +4750,19 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
>              }
>              break;
>  
> +        case OFPUTIL_NXAST_DEC_TTL:
> +            if (compose_dec_ttl(ctx)) {
> +                goto out;
> +            }
> +            break;
> +
>          case OFPUTIL_NXAST_EXIT:
>              ctx->exit = true;
>              break;
>          }
>      }
>  
> +out:
>      /* We've let OFPP_NORMAL and the learning action look at the packet,
>       * so drop it now if forwarding is disabled. */
>      if (port && !stp_forward_in_state(port->stp_state)) {
> @@ -4799,6 +4826,9 @@ xlate_actions(struct action_xlate_ctx *ctx,
>          case OFPC_FRAG_NX_MATCH:
>              /* Nothing to do. */
>              break;
> +
> +        case OFPC_INVALID_TTL_TO_CONTROLLER:
> +            NOT_REACHED();
>          }
>      }
>  
> diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
> index 29259e4..0504026 100644
> --- a/ofproto/ofproto.c
> +++ b/ofproto/ofproto.c
> @@ -1746,11 +1746,16 @@ handle_get_config_request(struct ofconn *ofconn, const struct ofp_header *oh)
>  {
>      struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
>      struct ofp_switch_config *osc;
> +    enum ofp_config_flags flags;
>      struct ofpbuf *buf;
>  
>      /* Send reply. */
>      osc = make_openflow_xid(sizeof *osc, OFPT_GET_CONFIG_REPLY, oh->xid, &buf);
> -    osc->flags = htons(ofproto->frag_handling);
> +    flags = ofproto->frag_handling;
> +    if (ofconn_get_invalid_ttl_to_controller(ofconn)) {
> +        flags |= OFPC_INVALID_TTL_TO_CONTROLLER;
> +    }
> +    osc->flags = htons(flags);
>      osc->miss_send_len = htons(ofconn_get_miss_send_len(ofconn));
>      ofconn_send_reply(ofconn, buf);
>  
> @@ -1779,6 +1784,8 @@ handle_set_config(struct ofconn *ofconn, const struct ofp_switch_config *osc)
>              }
>          }
>      }
> +    ofconn_set_invalid_ttl_to_controller(ofconn,
> +			 (flags & OFPC_INVALID_TTL_TO_CONTROLLER));
>  
>      ofconn_set_miss_send_len(ofconn, ntohs(osc->miss_send_len));
>  
> diff --git a/tests/ofp-print.at b/tests/ofp-print.at
> index 0619e98..85562b6 100644
> --- a/tests/ofp-print.at
> +++ b/tests/ofp-print.at
> @@ -269,7 +269,7 @@ AT_CHECK([ovs-ofctl ofp-print "\
>  c0 a8 00 02 27 2f 00 00 78 50 cc 5b 57 af 42 1e \
>  50 00 02 00 26 e8 00 00 00 00 00 00 00 00 \
>  "], [0], [dnl
> -OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=3 data_len=60 buffer=0x00000111
> +OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=3 (via no_match) data_len=60 buffer=0x00000111
>  priority:0,tunnel:0,in_port:0000,tci(0) mac(50:54:00:00:00:05->50:54:00:00:00:06) type:0800 proto:6 tos:0 ttl:64 ip(192.168.0.1->192.168.0.2) port(10031->0) tcp_csum:26e8
>  ])
>  AT_CLEANUP
> diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
> index 2c4e7c4..bb00714 100644
> --- a/tests/ofproto-dpif.at
> +++ b/tests/ofproto-dpif.at
> @@ -62,6 +62,38 @@ AT_CHECK([tail -1 stdout], [0],
>  OVS_VSWITCHD_STOP
>  AT_CLEANUP
>  
> +AT_SETUP([ofproto-dpif - dec_ttl])
> +OVS_VSWITCHD_START
> +AT_DATA([flows.txt], [dnl
> +table=0 in_port=1 action=dec_ttl,output:2,resubmit(1,1),output:4
> +table=1 in_port=1 action=dec_ttl,output:3
> +])
> +AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
> +AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)' -generate], [0], [stdout])
> +AT_CHECK([tail -2 stdout], [0],
> +  [Datapath actions: set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=1,frag=no)),2,4
> +This flow is not cachable.
> +])
> +AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=3,frag=no)'], [0], [stdout])
> +AT_CHECK([tail -1 stdout], [0],
> +  [Datapath actions: set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)),2,set(ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=1,frag=no)),3,4
> +])
> +AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=128,frag=no)'], [0], [stdout])
> +AT_CHECK([tail -1 stdout], [0],
> +  [Datapath actions: set(ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=127,frag=no)),2,set(ipv6(src=::1,dst=::2,label=0,proto=10,tclass=0x70,hlimit=126,frag=no)),3,4
> +])
> +
> +AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl --detach --pidfile 2> ofctl_monitor.log])
> +AT_CHECK([ovs-appctl ofproto/trace br0 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=2,frag=no)' -generate], [0], [stdout])
> +OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
> +AT_CHECK([cat ofctl_monitor.log], [0], [dnl
> +NXT_PACKET_IN (xid=0x0): table_id=1 total_len=42 in_port=1 tun_id=0x0 reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 (via invalid_ttl) data_len=42 (unbuffered)
> +priority:0,tunnel:0,in_port:0000,tci(0) mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:1 tos:0 ttl:1 ip(192.168.0.1->192.168.0.2)
> +])
> +OVS_VSWITCHD_STOP
> +AT_CLEANUP
> +
> +
>  AT_SETUP([ofproto-dpif - output, OFPP_NONE ingress port])
>  OVS_VSWITCHD_START(
>         [add-port br0 p1 -- set Interface p1 type=dummy --\
> @@ -209,13 +241,13 @@ done
>  
>  OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
>  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
> -OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 data_len=60 (unbuffered)
> +OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via no_match) data_len=60 (unbuffered)
>  priority:0,tunnel:0,in_port:0000,tci(0) mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0 ip(192.168.0.1->192.168.0.2) port(8->9) tcp_csum:0
>  dnl
> -OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 data_len=60 (unbuffered)
> +OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via no_match) data_len=60 (unbuffered)
>  priority:0,tunnel:0,in_port:0000,tci(0) mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0 ip(192.168.0.1->192.168.0.2) port(8->9) tcp_csum:0
>  dnl
> -OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 data_len=60 (unbuffered)
> +OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via no_match) data_len=60 (unbuffered)
>  priority:0,tunnel:0,in_port:0000,tci(0) mac(50:54:00:00:00:05->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0 ip(192.168.0.1->192.168.0.2) port(8->9) tcp_csum:0
>  ])
>  
> diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
> index 4bfd543..53d8619 100644
> --- a/utilities/ovs-ofctl.8.in
> +++ b/utilities/ovs-ofctl.8.in
> @@ -243,7 +243,7 @@ If a switch has no controller configured, or if
>  the configured controller is disconnected, no traffic is sent, so
>  monitoring will not show any traffic.
>  .
> -.IP "\fBmonitor \fIswitch\fR [\fImiss-len\fR]"
> +.IP "\fBmonitor \fIswitch\fR [\fImiss-len\fR] [\fIinvalid_ttl\fR]"
>  Connects to \fIswitch\fR and prints to the console all OpenFlow
>  messages received.  Usually, \fIswitch\fR should specify the name of a
>  bridge in the \fBovs\-vswitchd\fR database.
> @@ -256,6 +256,13 @@ does not send these and other asynchronous messages to an
>  specified on this argument.  (Thus, if \fImiss\-len\fR is not
>  specified, very little traffic will ordinarily be printed.)
>  .IP
> +.IP
> +If \fIinvalid_ttl\fR is passed, \fBovs\-ofctl\fR sends an OpenFlow ``set
> +configuration'' message at connection setup time that requests
> +\fIINVALID_TTL_TO_CONTROLLER\fR, so that \fBovs\-ofctl monitor\fR can
> +receive ``packets-in'' messages when TTL reaches zero on \fBdec_ttl\fR action.
> +.IP
> +
>  This command may be useful for debugging switch or controller
>  implementations.
>  .
> @@ -778,6 +785,16 @@ OpenFlow implementations do not support queuing at all.
>  Restores the queue to the value it was before any \fBset_queue\fR
>  actions were applied.
>  .
> +.IP \fBdec_ttl\fR
> +Decrement TTL of IPv4 packet or hop limit of IPv6 packet.  If the
> +TTL or hop limit is initially zero, no decrement occurs.  Instead,
> +a ``packet-in'' message with reason code \fBOFPR_INVALID_TTL\fR is
> +sent to each connected controller that has enabled receiving them,
> +if any.  Processing the current set of actions then stops.
> +However, if the current set of actions was reached through
> +``resubmit'' then remaining actions in outer levels resume
> +processing.
> +.
>  .IP \fBnote:\fR[\fIhh\fR]...
>  Does nothing at all.  Any number of bytes represented as hex digits
>  \fIhh\fR may be included.  Pairs of hex digits may be separated by
> diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
> index 6219f94..8a8b8b2 100644
> --- a/utilities/ovs-ofctl.c
> +++ b/utilities/ovs-ofctl.c
> @@ -794,6 +794,35 @@ set_packet_in_format(struct vconn *vconn,
>               ofputil_packet_in_format_to_string(packet_in_format));
>  }
>  
> +static int
> +monitor_set_invalid_ttl_to_controller(struct vconn *vconn)
> +{
> +    struct ofp_switch_config config;
> +    enum ofp_config_flags flags;
> +
> +    fetch_switch_config(vconn, &config);
> +    flags = ntohs(config.flags);
> +    if (!(flags & OFPC_INVALID_TTL_TO_CONTROLLER)) {
> +        /* Set the invalid ttl config. */
> +        flags |= OFPC_INVALID_TTL_TO_CONTROLLER;
> +
> +        config.flags = htons(flags);
> +        set_switch_config(vconn, &config);
> +
> +        /* Then retrieve the configuration to see if it really took.  OpenFlow
> +         * doesn't define error reporting for bad modes, so this is all we can
> +         * do. */
> +        fetch_switch_config(vconn, &config);
> +        flags = ntohs(config.flags);
> +        if (!(flags & OFPC_INVALID_TTL_TO_CONTROLLER)) {
> +            ovs_fatal(0, "setting invalid_ttl_to_controller failed (this "
> +                      "switch probably doesn't support mode)");
> +            return -EOPNOTSUPP;
> +        }
> +    }
> +    return 0;
> +}
> +
>  static void
>  monitor_vconn(struct vconn *vconn)
>  {
> @@ -876,6 +905,11 @@ do_monitor(int argc, char *argv[])
>          config.miss_send_len = htons(atoi(argv[2]));
>          set_switch_config(vconn, &config);
>      }
> +    if (argc > 3) {
> +        if (!strcmp(argv[3], "invalid_ttl")) {
> +            monitor_set_invalid_ttl_to_controller(vconn);
> +        }
> +    }
>      monitor_vconn(vconn);
>  }
>  
> @@ -1634,7 +1668,7 @@ do_ofp_print(int argc, char *argv[])
>  
>  static const struct command all_commands[] = {
>      { "show", 1, 1, do_show },
> -    { "monitor", 1, 2, do_monitor },
> +    { "monitor", 1, 3, do_monitor },
>      { "snoop", 1, 1, do_snoop },
>      { "dump-desc", 1, 1, do_dump_desc },
>      { "dump-tables", 1, 1, do_dump_tables },
> -- 
> 1.7.1
> 
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev



More information about the dev mailing list