Thanks,
I fixed and pushed patch to master.

--Pravin.

On Fri, Jan 13, 2012 at 5:17 PM, Ben Pfaff <b...@nicira.com> wrote:
> 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@openvswitch.org
>> http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to