Project 3 Rubric

The grading of this project follows a specifications grading approach. If you have not already done so, make sure to read our Grading section of the syllabus for more details.

You will receive two SNU scores for this project:

  • Completeness score: This score will be determined solely by the result of running the automated tests, as these give a measure of how complete your implementation is (i.e., how much of the assignment you implemented).

  • Code Quality score: This score is determined by a review of your code done by the course staff, and is based on three aspects of your code:

    • Correctness: This encompasses issues with your code that, while not explicitly captured by the tests, could lead to incorrect or inefficient behaviour in your code. This can include small mistakes in your code, as well as larger issues that reveal a lack of mastery in the material.

    • Design: This encompasses “qualities, many of which are intangible, that don’t have to do with (and exist to some extent independently of) the correct operation of your code.” (thanks to Adam Shaw for this concise phrasing).

    • Style: This encompasses your adherence to our Style Guide.

    • Documentation: You will be required to submit certain documentation on your code (the exact documentation is described below)

Submission Timeline

The exact timeline of submissions will be the following:

Submission

Requirements

Due Date

Project 3

chirouter (entire project)

Thursday, December 5th, 8pm

Resubmission (Optional)

You may submit a revised version to improve your Completeness score only

Friday, December 13th, 8pm

Unlike Projects 1 and 2, the resubmission can only be used to improve your Completeness score (i.e., the score on the automated tests). Since Project 3 is due by the end of the quarter, there is not enough to do a full resubmission-regrading cycle.

NOTE: To make a resubmission, you must make a “good-faith” submission by the project deadline. A good-faith submission is any submission where it is clear you have put in a substantial amount of effort to complete the project. Please note that scoring an N in Completeness is a sufficient (but not necessary) requirement for a submission to be considered a good-faith submission.

This means that, if you want to make a resubmission, you cannot skip the initial submission, or submit an effectively empty submission. The reason for this is that such a submission could score an S in Code Quality purely because most of the rubric items are moot (because there is little/no code to grade). Your resubmission could then score an S in Completeness, but then have major Code Quality issues.

In practical terms, this means the following:

  • If you are scoring an N on the tests in your initial submission, you have nothing to worry about. You can make a resubmission to raise your test score to an S.

  • If you skip the initial submission, or score a U in the tests, we reserve the right to regrade your code for Code Quality in the resubmission.

Completeness

The Completeness component will be determined by running the chirouter automated tests.

NOTE: In Project 3, you will be relying on manual testing to a greater extent than in Projects 1 and 2. The automated tests provide a convenient way to run all the tests and get a test score but, in general, if your code works when testing it manually, and fails the corresponding automated test, you should consider the test to have passed (you should make a note in the DOCUMENTATION.md file so the graders are aware of this)

Your SNU score will then be determined as follows:

Grade

Points on tests

Satisfactory

at least 90

Needs Improvement

at least 60

Unsatisfactory

less than 60

Code Quality

When assessing your code quality, there are a number of things we will be paying close attention to, and which we describe in the sections below (including major issues, labelled “[Major Issue]” that you should be particularly mindful of).

In general, your SNU score will be determined as follows:

  • Satisfactory: Your submission has a few of the issues described below (but no major issues).

  • Needs Improvement: Your submission has several of the issues described below, or at least one major issue. In general, major revisions are typically required to get up to an S.

  • Unsatisfactory: Your submission does not constitute a good-faith effort to complete the work. This includes not submitting any work at all, as well as submitting only placeholder code (e.g., code that includes functions for all the required IRC commands, but where the functions are empty or filled with “TODO”s, etc.)

That said, while the issues listed below are the main things we care about in this project, it is not possible for us to give you an exhaustive list of every single thing that could affect your code quality score. If you get a comment pointing out an issue in your code that we did not list below, take it as an opportunity to improve your work (and remember that you’ll have a chance to revise your work!)

Correctness

In this project, an incorrect implementation will almost always lead to some of the tests failing, so there are fewer things that we will be looking at when checking the correctness of your code. Nonetheless, we will be paying special attention to the following issues which would not be caught by the tests:

  • Automatically sending an ARP reply for any ARP request, without checking that the requested IP address matches the router interface’s IP address. Because the destination MAC address of ARP requests is set to the broadcast address, you will receive ARP requests that may not be intended for the router. You need to check the IP address in the ARP request itself to determine whether to reply to the ARP request.

  • Sending ARP replies with a broadcast destination address. ARP replies should be sent only to the host that originally sent the ARP request.

  • ICMP Port Unreachable: Checking for UDP or TCP payloads, but not both

  • Not checking the ARP cache before deciding whether to send an ARP request. If there is already a cached entry for a given IP address, there is no need to send an ARP request.

  • [Major issue] Not implementing IP forwarding at all, and instead forwarding all IP datagrams on all ports

  • [Major issue] Hardcoding any forwarding logic, instead of using the provided routing table

  • Writing IP forwarding, but processing the routing table incorrectly

  • Not locking/unlocking the ARP mutex when accessing the ARP cache or the list of pending ARP requests. Note: our code already locks the ARP mutex before calling the chirouter_arp_process_pending_req function, and unlocks it after it returns. No locking is necessary inside that function.

  • Managing Pending ARP Requests: Unconditionally creating new pending requests. If there is already an entry for IP address X in the pending ARP request list, and the router receives a new IP datagram with destination X, that datagram should be added to the list of withheld frames in the existing pending request. You should not create an entirely new pending request.

  • Removing pending requests from the pending ARP request list in chirouter_arp_process_pending_req , instead of returning ARP_REQ_REMOVE

  • Removing pending requests from the pending ARP request list before the request has been sent 5 times

  • Not removing a pending ARP request when an ARP reply is received, or when it has been sent 5 times already

  • Unconditionally sending a Time Exceeded reply if a forwardeable IP datagram arrives with TTL=1. The correct approach is to first determine whether it is a Host Unreachable and, if it is not, then send a Time Exceeded (meaning that forwardeable datagrams with TTL=1 must linger in the withheld frames list so we can determine whether there is actually a host with that IP).

Design

When assessing the design of your code, we will be paying special attention to the following:

  • [Major issue] Putting all your code in chirouter_process_ethernet_frame without dividing it into multiple functions.

  • Writing a single massive “Process IP datagram” function, without dividing it into multiple functions.

  • Repeating ICMP message creation logic in multiple places in your code, instead of writing a general-purpose “create an ICMP message” function

Style

We will be checking your general adherence to our Style Guide and, while we will not be checking that you follow every minute aspect of our style guide, we do expect you to follow a consistent style that asymptotically approaches the one specified in our style guide. That said, there are certain aspects we will be paying more attention to:

  • Documenting functions: Every function written by you must have a function comment with a brief description of what the function does, and a description of the parameters and the return value. Please note that not documenting your functions at all (as opposed to doing so inconsistently or not following the style guide) is considered a major issue.

  • Consistent indentation: Your code must follow one of the allowed indentation styles consistently.

  • Clarity: Your code must be easy to read and understand. This is a fairly subjective aspect, but remember that things like using variable names without descriptive names or using magic numbers will usually make your code harder to read.

  • [Major Issue] Using global variables, except when defining compile-time constants.

  • [Major Issue] Using goto statements, except in the very limited cases described in the style guide.

Documentation

Your submission must include a DOCUMENTATION.md file in the root of your repository with some specific documentation about the code you have written. If you do not include this file, Gradescope will reject your submission entirely. If you do include it, but the file does not provide the information we request below, this will be treated as a major issue in your submission.

The DOCUMENTATION.md file must follow the template below (the exact sections are explained further below):

Project 2
=========

Team members:
- TEAM MEMBER 1 (CNETID1)
- TEAM MEMBER 2 (CNETID2)

Test score: XXX / YYY

Additional functions
--------------------
- function1() in utils.c
- function2() in arp.c

Other code details / requests for feedback
------------------------------------------
<COMPLETE THIS SECTION>

Known omissions
---------------
<COMPLETE THIS SECTION>

Citations
---------
<COMPLETE THIS SECTION>

Below you can find more details on each of the sections. If you are not providing any information in a given section, please do not remove the section. Instead, just write N/A below it.

  • Team members: Include the names and CNetIDs of both team members.

  • Test score: Please include the test score you are seeing when running the tests on your computer. This will allow us to ensure that, when we run the tests, we are getting the same score.

  • Additional functions: If you added new functions to arp.c or utils.c, please list them here. You do not need to list every function you add to router.c

  • Other code details / requests for feedback: Use this section to provide any other information that may be relevant to the graders as they read through your code. If you would like us to provide feedback on any specific aspect of your work, you can also let us know in this section.

  • Known omissions: If you intentionally skipped any part of the project, or intentionally did not address any rubric items, please list them here. If we can provide any feedback that would help you address these rubric items, please let us know here as well.

  • Citations: Citations for use of Generative AI or external resources should be included, when possible, as code comments above any code where you relied on external sources. However, if you consulted a source that had a more broad impact on your work (and not on specific pieces of code), you can include the citation here. Additionally, if you had any high-level discussions about the project with other students in the class, please list their names here.

    Note: If the Generative AI platform you’re using does not allow you to easily generate a shareable link, please include a copy of the conversation(s) at the bottom of the DOCUMENTATION.md file.

Other Code Quality Issues

There are a couple of other issues that we care about across all projects:

  • Reinventing wheels that don’t need to be reinvented: In this class, we expect you to know how to use data structures like linked lists, hash tables, etc. (and how to choose the right data structure for a given task). However, this is a Networks class, not a Data Structures class, and you should not be spending any time implementing such data structures. The projects largely use the following data structure implementations:

    • utlist: A linked list library

    • uthash: A hash table for C structures

    • SDS: Simple Dynamic Strings

    Implementing your own linked list, hash table, etc. from scratch is considered a major issue. While you may think that implementing your own data structure is a worthwhile exercise, it invariably results in more work for the TAs and graders (as you will likely run into all sorts of issues and segfaults that could have been avoided by using a well-known and well-tested data structures library). Plus, it will be a much more worthwhile experience for you to understand how to incorporate an existing library into your own code.

  • Submitting code that doesn’t build: If you submit code that does not build on Gradescope’s autograder, but the graders can get it to build with some minor fixes (missing semicolons, parenthesis, etc.), this will just be treated as a major issue. However, if your code requires substantial work to get it to build, you will receive a U score.

    So, make sure you verify that the version of the code you submitted builds correctly on a supported software environment (see the Projects - Getting Started page for more details on this) Additionally, it is your responsibility to check that the code you submitted to Gradescope builds correctly. If it doesn’t, but it builds correctly on your end, please let us know so we can look into it.

  • Using printf instead of chilog: All the projects in this class use a simple logging library called chilog that is documented in each of the project specifications. You must use the chilog functions exclusively for printing logging or debug messages. Do not use printf() directly in your code. Please note that the chilog functions provide essentially the same functionality as printf, so there is no situation where printf would be necessary instead of chilog (using chilog consistently also means you will not have to scrub printf’s from your code before submitting it).

    Furthermore, all the messages at the INFO, WARNING, ERROR, and CRITICAL levels must be used only for their intended purposes (e.g., only use ERROR to print out actual errors in the execution of your program). You must use the DEBUG level only to print informative debug messages that would be understood by any developer trying to debug your code. You may use the TRACE level to print any debug message (including those that would only be understood by you). However, if your code is riddled with TRACE logging statements (including commented out ones) to the point where it is hard to read the code itself, we may penalize you for this. So, once a TRACE logging statement has served its purpose, we suggest you remove it (not just comment it out).

    You should assume that graders will run your code with logging at the INFO level, and will only use the DEBUG level if they need to debug an issue with your code. We will never run your code with logging at the TRACE level.

    Please note that, in assignments where you are responsible for writing the main function, you may use fprintf to print to standard error if there is an error that prevents the program from starting (e.g., if a command-line parameter has not been provided, etc.)

  • Grossly incorrect memory management: You should make sure to free any memory you malloc, but we will usually not penalize you unless you’ve been grossly negligent in your malloc’ing/freeing. You should also make sure to not “save” pointers to stack-allocated memory that is going to be deallocated. This can happen if you store a pointer to a functions’ local variable in a struct that is heap-allocated.